Permalink
Browse files

Handle errors in responses better.

Previously an "error row" would only throw "The 'id' was not found in the row definition." which is technically valid but unhelpful.

Now the view checks if a row is an error response and complains accordingly.

Change-Id: I529f37cb265e1977b338b1609a42f6a53da07cb4
  • Loading branch information...
1 parent 730fbce commit 02946ce29e351a558e127843eb6c2c24f225333a @enyim enyim committed with ingenthr Jul 26, 2011
Showing with 124 additions and 10 deletions.
  1. +16 −0 Couchbase/CouchbaseView.cs
  2. +25 −10 CouchbaseTests/CouchbaseViewTest_Parsing.cs
  3. +83 −0 CouchbaseTests/ErrorResponse.txt
View
@@ -271,6 +271,8 @@ public __Row(CouchbaseView owner, IDictionary<string, object> row)
if (row == null) throw new ArgumentNullException("row", "Missing row info");
+ CheckForError(row);
+
if (!row.TryGetValue("id", out this.id))
throw new InvalidOperationException("The value 'id' was not found in the row definition.");
@@ -283,6 +285,20 @@ public __Row(CouchbaseView owner, IDictionary<string, object> row)
this.info = row.AsReadOnly();
}
+ private static void CheckForError(IDictionary<string, object> row)
+ {
+ bool isError;
+
+ if (row.TryGetValue("error", out isError) && isError)
+ {
+ string reason;
+ if (row.TryGetValue("reason", out reason))
+ reason = " Reason: " + reason;
+
+ throw new InvalidOperationException("Failed to parse the row." + reason);
+ }
+ }
+
string IViewRow.ItemId
{
get { return this.id; }
@@ -14,10 +14,33 @@ namespace CouchbaseTests
{
public partial class CouchbaseViewTest
{
+ [TestMethod, DeploymentItem("ErrorResponse.txt")]
+ public void EnumerationShouldFailWhenErrorResponseIsReceived()
+ {
+ var view = GetViewFromResponse("ErrorResponse.txt");
+
+ Action tmp = () => view.ToList();
+
+ tmp.ShouldThrow<InvalidOperationException>();
+ }
+
[TestMethod, DeploymentItem("MixedResponse.txt")]
public void ItemsShouldBeReturnedByView()
{
- var content = File.ReadAllText(@"MixedResponse.txt");
+ var view = GetViewFromResponse("MixedResponse.txt");
+
+ var expectedKeys = (from index in Enumerable.Range(0, 10)
+ from prefix in new[] { "binary", "json" }
+ select prefix + "_" + index).ToList();
+
+ var resultKeys = view.Select(row => row.ItemId).ToList();
+
+ resultKeys.Should().BeEquivalentTo(expectedKeys);
+ }
+
+ private IView GetViewFromResponse(string fileName)
+ {
+ var content = File.ReadAllText(fileName);
var response = new Mock<IHttpResponse>();
response.Setup(r => r.GetResponseStream()).Returns(() => new MemoryStream(Encoding.UTF8.GetBytes(content), false));
@@ -32,15 +55,7 @@ public void ItemsShouldBeReturnedByView()
var locator = new Mock<IHttpClientLocator>();
locator.Setup(l => l.Locate(It.IsAny<string>())).Returns(client.Object);
- var view = new CouchbaseView(new Mock<IMemcachedClient>().Object, locator.Object, "doc", "index");
-
- var expectedKeys = (from index in Enumerable.Range(0, 10)
- from prefix in new[] { "binary", "json" }
- select prefix + "_" + index).ToList();
-
- var resultKeys = view.Select(row => row.ItemId).ToList();
-
- resultKeys.Should().BeEquivalentTo(expectedKeys);
+ return new CouchbaseView(new Mock<IMemcachedClient>().Object, locator.Object, "doc", "index");
}
}
}
@@ -0,0 +1,83 @@
+{"total_rows":254,"rows":[{"error":true,"from":"http://localhost:5984/_view_merge/?startkey=%22Mike%22","reason":"{\"error\":\"not_found\",\"reason\":\"missing\"}\n"},
+{"id":"PerryKrug:vs:AaronMiller","key":"PerryKrug:vs:AaronMiller","value":null},
+{"id":"PerryKrug:vs:BobWiederhold","key":"PerryKrug:vs:BobWiederhold","value":null},
+{"id":"PerryKrug:vs:DaleHarvey","key":"PerryKrug:vs:DaleHarvey","value":null},
+{"id":"PerryKrug:vs:DamienKatz","key":"PerryKrug:vs:DamienKatz","value":null},
+{"id":"PerryKrug:vs:DustinSallings","key":"PerryKrug:vs:DustinSallings","value":null},
+{"id":"PerryKrug:vs:JamesPhillips","key":"PerryKrug:vs:JamesPhillips","value":null},
+{"id":"PerryKrug:vs:JChrisAnderson","key":"PerryKrug:vs:JChrisAnderson","value":null},
+{"id":"PerryKrug:vs:LeilaIravini","key":"PerryKrug:vs:LeilaIravini","value":null},
+{"id":"PerryKrug:vs:MelindaWilken","key":"PerryKrug:vs:MelindaWilken","value":null},
+{"id":"PerryKrug:vs:StevenMih","key":"PerryKrug:vs:StevenMih","value":null},
+{"id":"PerryKrug:vs:SteveYen","key":"PerryKrug:vs:SteveYen","value":null},
+{"id":"PerryKrug:vs:TonyNguyen","key":"PerryKrug:vs:TonyNguyen","value":null},
+{"id":"PerryKrug:vs:VolkerMische","key":"PerryKrug:vs:VolkerMische","value":null},
+{"id":"StevenMih","key":"StevenMih","value":null},
+{"id":"StevenMih:vs:AaronMiller","key":"StevenMih:vs:AaronMiller","value":null},
+{"id":"StevenMih:vs:DaleHarvey","key":"StevenMih:vs:DaleHarvey","value":null},
+{"id":"StevenMih:vs:DamienKatz","key":"StevenMih:vs:DamienKatz","value":null},
+{"id":"StevenMih:vs:DustinSallings","key":"StevenMih:vs:DustinSallings","value":null},
+{"id":"StevenMih:vs:FrankWeigel","key":"StevenMih:vs:FrankWeigel","value":null},
+{"id":"StevenMih:vs:JamesPhillips","key":"StevenMih:vs:JamesPhillips","value":null},
+{"id":"StevenMih:vs:JanLehnardt","key":"StevenMih:vs:JanLehnardt","value":null},
+{"id":"StevenMih:vs:LeilaIravini","key":"StevenMih:vs:LeilaIravini","value":null},
+{"id":"StevenMih:vs:MattIngenthron","key":"StevenMih:vs:MattIngenthron","value":null},
+{"id":"StevenMih:vs:StevenMih","key":"StevenMih:vs:StevenMih","value":null},
+{"id":"StevenMih:vs:TonyNguyen","key":"StevenMih:vs:TonyNguyen","value":null},
+{"id":"StevenMih:vs:VolkerMische","key":"StevenMih:vs:VolkerMische","value":null},
+{"id":"SteveYen","key":"SteveYen","value":null},
+{"id":"SteveYen:vs:AaronMiller","key":"SteveYen:vs:AaronMiller","value":null},
+{"id":"SteveYen:vs:AliakseyKandratsenka","key":"SteveYen:vs:AliakseyKandratsenka","value":null},
+{"id":"SteveYen:vs:DaleHarvey","key":"SteveYen:vs:DaleHarvey","value":null},
+{"id":"SteveYen:vs:DustinSallings","key":"SteveYen:vs:DustinSallings","value":null},
+{"id":"SteveYen:vs:JamesPhillips","key":"SteveYen:vs:JamesPhillips","value":null},
+{"id":"SteveYen:vs:JChrisAnderson","key":"SteveYen:vs:JChrisAnderson","value":null},
+{"id":"SteveYen:vs:MattIngenthron","key":"SteveYen:vs:MattIngenthron","value":null},
+{"id":"SteveYen:vs:PerryKrug","key":"SteveYen:vs:PerryKrug","value":null},
+{"id":"SteveYen:vs:SteveYen","key":"SteveYen:vs:SteveYen","value":null},
+{"id":"SteveYen:vs:TonyNguyen","key":"SteveYen:vs:TonyNguyen","value":null},
+{"id":"TonyNguyen","key":"TonyNguyen","value":null},
+{"id":"TonyNguyen:vs:AaronMiller","key":"TonyNguyen:vs:AaronMiller","value":null},
+{"id":"TonyNguyen:vs:AliakseyKandratsenka","key":"TonyNguyen:vs:AliakseyKandratsenka","value":null},
+{"id":"TonyNguyen:vs:BobWiederhold","key":"TonyNguyen:vs:BobWiederhold","value":null},
+{"id":"TonyNguyen:vs:DaleHarvey","key":"TonyNguyen:vs:DaleHarvey","value":null},
+{"id":"TonyNguyen:vs:DustinSallings","key":"TonyNguyen:vs:DustinSallings","value":null},
+{"id":"TonyNguyen:vs:FrankWeigel","key":"TonyNguyen:vs:FrankWeigel","value":null},
+{"id":"TonyNguyen:vs:JamesPhillips","key":"TonyNguyen:vs:JamesPhillips","value":null},
+{"id":"TonyNguyen:vs:JanLehnardt","key":"TonyNguyen:vs:JanLehnardt","value":null},
+{"id":"TonyNguyen:vs:JChrisAnderson","key":"TonyNguyen:vs:JChrisAnderson","value":null},
+{"id":"TonyNguyen:vs:LeilaIravini","key":"TonyNguyen:vs:LeilaIravini","value":null},
+{"id":"TonyNguyen:vs:MattIngenthron","key":"TonyNguyen:vs:MattIngenthron","value":null},
+{"id":"TonyNguyen:vs:MelindaWilken","key":"TonyNguyen:vs:MelindaWilken","value":null},
+{"id":"TonyNguyen:vs:PerryKrug","key":"TonyNguyen:vs:PerryKrug","value":null},
+{"id":"TonyNguyen:vs:StevenMih","key":"TonyNguyen:vs:StevenMih","value":null},
+{"id":"TonyNguyen:vs:SteveYen","key":"TonyNguyen:vs:SteveYen","value":null},
+{"id":"TonyNguyen:vs:TrondNorbye","key":"TonyNguyen:vs:TrondNorbye","value":null},
+{"id":"TrondNorbye:vs:AliakseyKandratsenka","key":"TrondNorbye:vs:AliakseyKandratsenka","value":null},
+{"id":"TrondNorbye:vs:BobWiederhold","key":"TrondNorbye:vs:BobWiederhold","value":null},
+{"id":"TrondNorbye:vs:DamienKatz","key":"TrondNorbye:vs:DamienKatz","value":null},
+{"id":"TrondNorbye:vs:DustinSallings","key":"TrondNorbye:vs:DustinSallings","value":null},
+{"id":"TrondNorbye:vs:FrankWeigel","key":"TrondNorbye:vs:FrankWeigel","value":null},
+{"id":"TrondNorbye:vs:JanLehnardt","key":"TrondNorbye:vs:JanLehnardt","value":null},
+{"id":"TrondNorbye:vs:JChrisAnderson","key":"TrondNorbye:vs:JChrisAnderson","value":null},
+{"id":"TrondNorbye:vs:MattIngenthron","key":"TrondNorbye:vs:MattIngenthron","value":null},
+{"id":"TrondNorbye:vs:MelindaWilken","key":"TrondNorbye:vs:MelindaWilken","value":null},
+{"id":"TrondNorbye:vs:PerryKrug","key":"TrondNorbye:vs:PerryKrug","value":null},
+{"id":"TrondNorbye:vs:StevenMih","key":"TrondNorbye:vs:StevenMih","value":null},
+{"id":"TrondNorbye:vs:SteveYen","key":"TrondNorbye:vs:SteveYen","value":null},
+{"id":"TrondNorbye:vs:TonyNguyen","key":"TrondNorbye:vs:TonyNguyen","value":null},
+{"id":"TrondNorbye:vs:TrondNorbye","key":"TrondNorbye:vs:TrondNorbye","value":null},
+{"id":"VolkerMische","key":"VolkerMische","value":null},
+{"id":"VolkerMische:vs:AliakseyKandratsenka","key":"VolkerMische:vs:AliakseyKandratsenka","value":null},
+{"id":"VolkerMische:vs:BobWiederhold","key":"VolkerMische:vs:BobWiederhold","value":null},
+{"id":"VolkerMische:vs:DamienKatz","key":"VolkerMische:vs:DamienKatz","value":null},
+{"id":"VolkerMische:vs:DustinSallings","key":"VolkerMische:vs:DustinSallings","value":null},
+{"id":"VolkerMische:vs:FrankWeigel","key":"VolkerMische:vs:FrankWeigel","value":null},
+{"id":"VolkerMische:vs:JanLehnardt","key":"VolkerMische:vs:JanLehnardt","value":null},
+{"id":"VolkerMische:vs:JChrisAnderson","key":"VolkerMische:vs:JChrisAnderson","value":null},
+{"id":"VolkerMische:vs:MattIngenthron","key":"VolkerMische:vs:MattIngenthron","value":null},
+{"id":"VolkerMische:vs:MelindaWilken","key":"VolkerMische:vs:MelindaWilken","value":null},
+{"id":"VolkerMische:vs:PerryKrug","key":"VolkerMische:vs:PerryKrug","value":null},
+{"id":"VolkerMische:vs:TonyNguyen","key":"VolkerMische:vs:TonyNguyen","value":null},
+{"id":"VolkerMische:vs:TrondNorbye","key":"VolkerMische:vs:TrondNorbye","value":null}
+]}

0 comments on commit 02946ce

Please sign in to comment.