diff --git a/Client.Tests/Client.Tests.csproj b/Client.Tests/Client.Tests.csproj
index db984fc..682fa29 100644
--- a/Client.Tests/Client.Tests.csproj
+++ b/Client.Tests/Client.Tests.csproj
@@ -13,7 +13,7 @@
v4.0
512
..\
- true
+ false
true
@@ -52,15 +52,18 @@
-
+
-
+
+
+
+
+
-
-
+
diff --git a/Client.Tests/CursorTests.cs b/Client.Tests/CursorTests.cs
new file mode 100644
index 0000000..1314cbd
--- /dev/null
+++ b/Client.Tests/CursorTests.cs
@@ -0,0 +1,160 @@
+using Client;
+using Client.Model;
+using Moq;
+using NUnit.Framework;
+using RestSharp;
+using System;
+using System.Collections.Generic;
+using System.Linq.Expressions;
+
+
+namespace Client.Tests
+{
+ [TestFixture]
+ public class CursorTests
+ {
+ [Test]
+ public void SingleSegmentSmokeTest()
+ {
+ var response = new RestResponse {
+ StatusCode = System.Net.HttpStatusCode.OK,
+ Content = "{\"data\":[{\"t\":\"2012-03-27T00:00:00.000-05:00\",\"v\":12.34},{\"t\":\"2012-03-27T01:00:00.000-05:00\",\"v\":23.45}],\"rollup\":null}"
+ };
+ var mockclient = new Mock();
+ mockclient.Setup(cl => cl.Execute(It.IsAny())).Returns(response);
+ var client = TestCommon.GetClient(mockclient.Object);
+ var cursor = client.ReadCursorByKey("key1", new DateTime(2012, 3, 27), new DateTime(2012, 3, 28));
+
+ var expected = new List {
+ new DataPoint(new DateTime(2012, 3, 27, 0, 0, 0), 12.34),
+ new DataPoint(new DateTime(2012, 3, 27, 1, 0, 0), 23.45)
+ };
+ var output = new List();
+ foreach(DataPoint dp in cursor)
+ {
+ output.Add(dp);
+ }
+ Assert.AreEqual(expected, output);
+ }
+
+ [Test]
+ public void MultipleSegmentSmokeTest()
+ {
+ var response1 = new RestResponse {
+ StatusCode = System.Net.HttpStatusCode.OK,
+ Content = "{\"data\":[{\"t\":\"2012-03-27T00:00:00.000-05:00\",\"v\":12.34},{\"t\":\"2012-03-27T01:00:00.000-05:00\",\"v\":23.45}],\"rollup\":null}"
+ };
+ response1.Headers.Add(new Parameter {
+ Name = "Link",
+ Value = "; rel=\"next\""
+ });
+ var response2 = new RestResponse {
+ StatusCode = System.Net.HttpStatusCode.OK,
+ Content = "{\"data\":[{\"t\":\"2012-03-27T02:00:00.000-05:00\",\"v\":34.56}],\"rollup\":null}"
+ };
+ var calls = 0;
+ RestResponse[] responses = { response1, response2 };
+ var mockclient = new Mock();
+ mockclient.Setup(cl => cl.Execute(It.IsAny())).Returns(() => responses[calls]).Callback(() => calls++);
+
+ var client = TestCommon.GetClient(mockclient.Object);
+ var cursor = client.ReadCursorByKey("key1", new DateTime(2012, 3, 27), new DateTime(2012, 3, 28));
+
+ var expected = new List {
+ new DataPoint(new DateTime(2012, 3, 27, 0, 0, 0), 12.34),
+ new DataPoint(new DateTime(2012, 3, 27, 1, 0, 0), 23.45),
+ new DataPoint(new DateTime(2012, 3, 27, 2, 0, 0), 34.56)
+ };
+ var output = new List();
+ foreach(DataPoint dp in cursor)
+ {
+ output.Add(dp);
+ }
+ Assert.AreEqual(expected, output);
+ }
+
+ [Test]
+ public void RequestMethod()
+ {
+ var response = new RestResponse {
+ StatusCode = System.Net.HttpStatusCode.OK,
+ Content = "{\"data\":[{\"t\":\"2012-03-27T00:00:00.000-05:00\",\"v\":12.34},{\"t\":\"2012-03-27T01:00:00.000-05:00\",\"v\":23.45}],\"rollup\":null}"
+ };
+ var mockclient = TestCommon.GetMockRestClient(response);
+ var client = TestCommon.GetClient(mockclient.Object);
+ client.ReadCursorByKey("key1", new DateTime(2012, 3, 27), new DateTime(2012, 3, 28));
+
+ Expression> assertion = req => req.Method == Method.GET;
+ mockclient.Verify(cl => cl.Execute(It.Is(assertion)));
+ }
+
+ [Test]
+ public void RequestStartTime()
+ {
+ var response = new RestResponse {
+ StatusCode = System.Net.HttpStatusCode.OK,
+ Content = "{\"data\":[{\"t\":\"2012-03-27T00:00:00.000-05:00\",\"v\":12.34},{\"t\":\"2012-03-27T01:00:00.000-05:00\",\"v\":23.45}],\"rollup\":null}"
+ };
+ var mockclient = TestCommon.GetMockRestClient(response);
+ var client = TestCommon.GetClient(mockclient.Object);
+ var start = new DateTime(2012, 6, 23);
+ var end = new DateTime(2012, 6, 24);
+
+ client.ReadCursorByKey("testkey", start, end, IntervalParameter.Raw());
+
+ Expression> assertion = req => TestCommon.ContainsParameter(req.Parameters, "start", "2012-06-23T00:00:00.000-05:00");
+ mockclient.Verify(cl => cl.Execute(It.Is(assertion)));
+ }
+
+ [Test]
+ public void RequestEndTime()
+ {
+ var response = new RestResponse {
+ StatusCode = System.Net.HttpStatusCode.OK,
+ Content = "{\"data\":[{\"t\":\"2012-03-27T00:00:00.000-05:00\",\"v\":12.34},{\"t\":\"2012-03-27T01:00:00.000-05:00\",\"v\":23.45}],\"rollup\":null}"
+ };
+ var mockclient = TestCommon.GetMockRestClient(response);
+ var client = TestCommon.GetClient(mockclient.Object);
+ var start = new DateTime(2012, 6, 23);
+ var end = new DateTime(2012, 6, 24);
+
+ client.ReadCursorByKey("testkey", start, end, IntervalParameter.Raw());
+
+ Expression> assertion = req => TestCommon.ContainsParameter(req.Parameters, "end", "2012-06-24T00:00:00.000-05:00");
+ mockclient.Verify(cl => cl.Execute(It.Is(assertion)));
+ }
+
+ [Test]
+ public void RequestUrl()
+ {
+ var response = new RestResponse {
+ StatusCode = System.Net.HttpStatusCode.OK,
+ Content = "{\"data\":[{\"t\":\"2012-03-27T00:00:00.000-05:00\",\"v\":12.34},{\"t\":\"2012-03-27T01:00:00.000-05:00\",\"v\":23.45}],\"rollup\":null}"
+ };
+ var mockclient = TestCommon.GetMockRestClient(response);
+ var client = TestCommon.GetClient(mockclient.Object);
+
+ client.ReadCursorByKey("testkey", new DateTime(2012, 06, 23), new DateTime(2012, 06, 24), IntervalParameter.Raw());
+
+ mockclient.Verify(cl => cl.Execute(It.Is(req => req.Resource == "/{version}/series/{property}/{value}/data/segment/")));
+ mockclient.Verify(cl => cl.Execute(It.Is(req => TestCommon.ContainsParameter(req.Parameters, "property", "key"))));
+ mockclient.Verify(cl => cl.Execute(It.Is(req => TestCommon.ContainsParameter(req.Parameters, "value", "testkey"))));
+ }
+
+ [Test]
+ public void RequestInterval()
+ {
+ var response = new RestResponse {
+ StatusCode = System.Net.HttpStatusCode.OK,
+ Content = "{\"data\":[{\"t\":\"2012-03-27T00:00:00.000-05:00\",\"v\":12.34},{\"t\":\"2012-03-27T01:00:00.000-05:00\",\"v\":23.45}],\"rollup\":null}"
+ };
+ var mockclient = TestCommon.GetMockRestClient(response);
+ var client = TestCommon.GetClient(mockclient.Object);
+
+ client.ReadCursorByKey("testkey", new DateTime(2012, 06, 23), new DateTime(2012, 06, 24), IntervalParameter.Raw());
+
+ Expression> assertion = req => TestCommon.ContainsParameter(req.Parameters, "interval", "raw");
+ mockclient.Verify(cl => cl.Execute(It.Is(assertion)));
+ }
+ }
+}
diff --git a/Client.Tests/DeleteTests.cs b/Client.Tests/DeleteTests.cs
index 8e55d32..c3ae57d 100644
--- a/Client.Tests/DeleteTests.cs
+++ b/Client.Tests/DeleteTests.cs
@@ -23,7 +23,7 @@ public void SmokeTest()
client.DeleteById("series-id", new DateTime(2012, 1, 1), new DateTime(2012, 1, 1, 1, 0, 0));
mockclient.Verify(cl => cl.Execute(It.Is(req => req.Method == Method.DELETE)));
- mockclient.Verify(cl => cl.Execute(It.Is(req => req.Resource == "/series/{property}/{value}/data")));
+ mockclient.Verify(cl => cl.Execute(It.Is(req => req.Resource == "/{version}/series/{property}/{value}/data")));
mockclient.Verify(cl => cl.Execute(It.Is(req => TestCommon.ContainsParameter(req.Parameters, "start", "2012-01-01T00:00:00.000-06:00"))));
mockclient.Verify(cl => cl.Execute(It.Is(req => TestCommon.ContainsParameter(req.Parameters, "end", "2012-01-01T01:00:00.000-06:00"))));
mockclient.Verify(cl => cl.Execute(It.Is(req => TestCommon.ContainsParameter(req.Parameters, "property", "id"))));
@@ -39,7 +39,7 @@ public void Key()
client.DeleteByKey("series-key", new DateTime(2012, 1, 1), new DateTime(2012, 1, 1, 1, 0, 0));
mockclient.Verify(cl => cl.Execute(It.Is(req => req.Method == Method.DELETE)));
- mockclient.Verify(cl => cl.Execute(It.Is(req => req.Resource == "/series/{property}/{value}/data")));
+ mockclient.Verify(cl => cl.Execute(It.Is(req => req.Resource == "/{version}/series/{property}/{value}/data")));
mockclient.Verify(cl => cl.Execute(It.Is(req => TestCommon.ContainsParameter(req.Parameters, "start", "2012-01-01T00:00:00.000-06:00"))));
mockclient.Verify(cl => cl.Execute(It.Is(req => TestCommon.ContainsParameter(req.Parameters, "end", "2012-01-01T01:00:00.000-06:00"))));
mockclient.Verify(cl => cl.Execute(It.Is(req => TestCommon.ContainsParameter(req.Parameters, "property", "key"))));
diff --git a/Client.Tests/IncrementTests.cs b/Client.Tests/IncrementTests.cs
index dd5b736..dec47e6 100644
--- a/Client.Tests/IncrementTests.cs
+++ b/Client.Tests/IncrementTests.cs
@@ -23,7 +23,7 @@ public void Request()
data.Add(new DataPoint(DateTime.Now, valueToAdd));
client.IncrementByKey("key", data);
- Expression> assertion = req => req.Method == Method.POST && req.Resource == "/series/{property}/{value}/increment/";
+ Expression> assertion = req => req.Method == Method.POST && req.Resource == "/{version}/series/{property}/{value}/increment/";
mockclient.Verify(cl => cl.Execute(It.Is(assertion)));
}
diff --git a/Client.Tests/JsonDeserializationTests.cs b/Client.Tests/Json/JsonDeserializationTests.cs
similarity index 81%
rename from Client.Tests/JsonDeserializationTests.cs
rename to Client.Tests/Json/JsonDeserializationTests.cs
index fcc0cba..64c1418 100644
--- a/Client.Tests/JsonDeserializationTests.cs
+++ b/Client.Tests/Json/JsonDeserializationTests.cs
@@ -1,4 +1,5 @@
-using Client.Model;
+using Client.Json;
+using Client.Model;
using Moq;
using NUnit.Framework;
using RestSharp;
@@ -172,5 +173,46 @@ public void EmptySummary()
Assert.AreEqual(0, result.Summary.Count);
}
}
+
+ [TestFixture]
+ class SummaryTests
+ {
+ static string jsonSummary = @"{
+ ""mean"": 3.00,
+ ""sum"": 12.00,
+ ""min"": 2.00,
+ ""max"": 4.00,
+ ""stddev"": 0.8165,
+ ""ss"": 2.00,
+ ""count"": 4
+ }";
+
+ [Test]
+ public void SmokeTest()
+ {
+ var jsonResponse = new RestResponse {
+ Content = SummaryTests.jsonSummary
+ };
+
+ var result = JsonDeserializationTests.deserializer.Deserialize(jsonResponse);
+ Assert.AreEqual(3.0, result["mean"]);
+ Assert.AreEqual(12.0, result["sum"]);
+ Assert.AreEqual(2.0, result["min"]);
+ Assert.AreEqual(4.0, result["max"]);
+ Assert.AreEqual(0.8165, result["stddev"]);
+ Assert.AreEqual(2.0, result["ss"]);
+ Assert.AreEqual(4, result["count"]);
+ }
+
+ [Test]
+ public void Empty()
+ {
+ var jsonResponse = new RestResponse {
+ Content = "{}"
+ };
+ var result = JsonDeserializationTests.deserializer.Deserialize(jsonResponse);
+ Assert.AreEqual(0, result.Count);
+ }
+ }
}
}
diff --git a/Client.Tests/JsonSerializationTests.cs b/Client.Tests/Json/JsonSerializationTests.cs
similarity index 99%
rename from Client.Tests/JsonSerializationTests.cs
rename to Client.Tests/Json/JsonSerializationTests.cs
index 0cb4745..8129fe8 100644
--- a/Client.Tests/JsonSerializationTests.cs
+++ b/Client.Tests/Json/JsonSerializationTests.cs
@@ -1,4 +1,5 @@
-using Client.Model;
+using Client.Json;
+using Client.Model;
using Moq;
using NUnit.Framework;
using RestSharp;
diff --git a/Client.Tests/DataPointModelTests.cs b/Client.Tests/Model/DataPointTests.cs
similarity index 97%
rename from Client.Tests/DataPointModelTests.cs
rename to Client.Tests/Model/DataPointTests.cs
index a320374..8082781 100644
--- a/Client.Tests/DataPointModelTests.cs
+++ b/Client.Tests/Model/DataPointTests.cs
@@ -9,7 +9,7 @@
namespace Client.Tests
{
[TestFixture]
- class DataPointModelTests
+ class DataPointTests
{
[Test]
public void Unequality_Timestamp()
diff --git a/Client.Tests/Model/SegmentTests.cs b/Client.Tests/Model/SegmentTests.cs
new file mode 100644
index 0000000..4ef22cf
--- /dev/null
+++ b/Client.Tests/Model/SegmentTests.cs
@@ -0,0 +1,65 @@
+using Client.Model;
+using NUnit.Framework;
+using System;
+using System.Collections.Generic;
+
+
+namespace Client.Tests
+{
+ [TestFixture]
+ public class SegmentTests
+ {
+ [Test]
+ public void Constructor()
+ {
+ List data = new List { new DataPoint(new DateTime(2012, 3, 27), 12.34) };
+ Segment segment = new Segment(data, "next");
+ Assert.AreEqual(data, segment.Data);
+ Assert.AreEqual("next", segment.NextUrl);
+ }
+
+ [Test]
+ public void Deserialize()
+ {
+ string content = "{\"data\":[{\"t\":\"2012-03-27T00:00:00.000-05:00\",\"v\":12.34}],\"rollup\":null}";
+ RestSharp.RestResponse response = new RestSharp.RestResponse {
+ StatusCode = System.Net.HttpStatusCode.OK,
+ Content = content
+ };
+ RestSharp.Parameter link = new RestSharp.Parameter {
+ Name = "Link",
+ Value = "; rel=\"next\""
+ };
+ response.Headers.Add(link);
+
+ Segment segment = Segment.FromResponse(response);
+ Segment expected = new Segment(new List{new DataPoint(new DateTime(2012, 3, 27), 12.34)}, "/v1/series/key/key1/data/segment/?start=2012-01-01&end=2012-01-02");
+ Assert.AreEqual(expected.Data, segment.Data);
+ Assert.AreEqual(expected.NextUrl, segment.NextUrl);
+ }
+
+ [Test]
+ public void Iterator()
+ {
+ string content = "{\"data\":[{\"t\":\"2012-03-27T00:00:00.000-05:00\",\"v\":12.34},{\"t\":\"2012-03-27T01:00:00.000-05:00\",\"v\":23.45}],\"rollup\":null}";
+ RestSharp.RestResponse response = new RestSharp.RestResponse
+ {
+ StatusCode = System.Net.HttpStatusCode.OK,
+ Content = content
+ };
+
+ Segment segment = Segment.FromResponse(response);
+ List expected = new List {
+ new DataPoint(new DateTime(2012, 3, 27, 0, 0, 0), 12.34),
+ new DataPoint(new DateTime(2012, 3, 27, 1, 0, 0), 23.45)
+ };
+
+ List output = new List();
+ foreach(DataPoint dp in segment)
+ {
+ output.Add(dp);
+ }
+ Assert.AreEqual(expected, output);
+ }
+ }
+}
diff --git a/Client.Tests/SeriesModelTests.cs b/Client.Tests/Model/SeriesTests.cs
similarity index 98%
rename from Client.Tests/SeriesModelTests.cs
rename to Client.Tests/Model/SeriesTests.cs
index 1a0c65e..968c5dc 100644
--- a/Client.Tests/SeriesModelTests.cs
+++ b/Client.Tests/Model/SeriesTests.cs
@@ -9,7 +9,7 @@
namespace Client.Tests
{
[TestFixture]
- class SeriesModelTests
+ class SeriesTests
{
[Test]
public void Equality()
diff --git a/Client.Tests/ReadTests.cs b/Client.Tests/ReadTests.cs
index 6d6976a..67bccad 100644
--- a/Client.Tests/ReadTests.cs
+++ b/Client.Tests/ReadTests.cs
@@ -83,7 +83,7 @@ public void RequestUrl()
client.ReadByKey("testkey", new DateTime(2012, 06, 23), new DateTime(2012, 06, 24), IntervalParameter.Raw());
- mockclient.Verify(cl => cl.Execute(It.Is(req => req.Resource == "/series/{property}/{value}/data")));
+ mockclient.Verify(cl => cl.Execute(It.Is(req => req.Resource == "/{version}/series/{property}/{value}/data")));
mockclient.Verify(cl => cl.Execute(It.Is(req => TestCommon.ContainsParameter(req.Parameters, "property", "key"))));
mockclient.Verify(cl => cl.Execute(It.Is(req => TestCommon.ContainsParameter(req.Parameters, "value", "testkey"))));
}
@@ -108,7 +108,7 @@ public void RequestMethod_Id()
client.ReadById("testid", new DateTime(2012, 06, 23), new DateTime(2012, 06, 24), IntervalParameter.Raw());
- mockclient.Verify(cl => cl.Execute(It.Is(req => req.Resource == "/series/{property}/{value}/data")));
+ mockclient.Verify(cl => cl.Execute(It.Is(req => req.Resource == "/{version}/series/{property}/{value}/data")));
mockclient.Verify(cl => cl.Execute(It.Is(req => TestCommon.ContainsParameter(req.Parameters, "property", "id"))));
mockclient.Verify(cl => cl.Execute(It.Is(req => TestCommon.ContainsParameter(req.Parameters, "value", "testid"))));
}
@@ -178,7 +178,7 @@ public void RequestUrl()
filter.AddKey("series2");
client.ReadMultipleSeries(new DateTime(2012, 06, 23), new DateTime(2012, 06, 24), filter, IntervalParameter.Raw());
- Expression> assertion = req => req.Resource == "/data/";
+ Expression> assertion = req => req.Resource == "/{version}/data/";
mockclient.Verify(cl => cl.Execute>(It.Is(assertion)));
}
diff --git a/Client.Tests/SeriesTests.cs b/Client.Tests/SeriesTests.cs
index fd35a74..072bd65 100644
--- a/Client.Tests/SeriesTests.cs
+++ b/Client.Tests/SeriesTests.cs
@@ -73,7 +73,7 @@ public void RequestUrl()
client.CreateSeries("series-key");
- mockclient.Verify(cl => cl.Execute(It.Is(req => req.Resource == "/series/")));
+ mockclient.Verify(cl => cl.Execute(It.Is(req => req.Resource == "/{version}/series/")));
}
[Test]
@@ -138,7 +138,7 @@ public void RequestUrl()
client.GetSeriesById("series-id");
- mockclient.Verify(cl => cl.Execute(It.Is(req => req.Resource == "/series/id/{id}")));
+ mockclient.Verify(cl => cl.Execute(It.Is(req => req.Resource == "/{version}/series/id/{id}")));
}
[Test]
@@ -198,7 +198,7 @@ public void KeyRequestUrl()
client.GetSeriesByKey("series-key");
- mockclient.Verify(cl => cl.Execute(It.Is(req => req.Resource == "/series/key/{key}")));
+ mockclient.Verify(cl => cl.Execute(It.Is(req => req.Resource == "/{version}/series/key/{key}")));
}
[Test]
@@ -264,7 +264,7 @@ public void RequestUrl()
client.ListSeries();
- mockclient.Verify(cl => cl.Execute>(It.Is(req => req.Resource == "/series")));
+ mockclient.Verify(cl => cl.Execute>(It.Is(req => req.Resource == "/{version}/series/")));
}
[Test]
@@ -348,7 +348,7 @@ public void RequestUrl()
client.UpdateSeries(seriesResponse);
- mockclient.Verify(cl => cl.Execute(It.Is(req => req.Resource == "/series/id/{id}/")));
+ mockclient.Verify(cl => cl.Execute(It.Is(req => req.Resource == "/{version}/series/id/{id}/")));
mockclient.Verify(cl => cl.Execute(It.Is(req => TestCommon.ContainsParameter(req.Parameters, "id", "series-id"))));
}
}
diff --git a/Client.Tests/SummaryTests.cs b/Client.Tests/SummaryTests.cs
new file mode 100644
index 0000000..c7482dd
--- /dev/null
+++ b/Client.Tests/SummaryTests.cs
@@ -0,0 +1,87 @@
+using Client;
+using Client.Model;
+using Moq;
+using NUnit.Framework;
+using RestSharp;
+using System;
+using System.Collections.Generic;
+using System.Linq.Expressions;
+
+
+namespace Client.Tests
+{
+ [TestFixture]
+ public class SummaryTests
+ {
+ [Test]
+ public void SmokeTest()
+ {
+ var expected = new Summary {
+ {"mean", 3.0},
+ {"sum", 12.0},
+ {"min", 2.0},
+ {"max", 4.0},
+ {"stddev", 0.8165},
+ {"ss", 2.0},
+ {"count", 4}
+ };
+
+ var mockclient = TestCommon.GetMockRestClient(expected);
+ var client = TestCommon.GetClient(mockclient.Object);
+ var summary = client.ReadSummaryByKey("key1", new DateTime(2012, 3, 27), new DateTime(2012, 3, 28));
+ Assert.AreEqual(expected, summary);
+ }
+
+ [Test]
+ public void RequestMethod()
+ {
+ var mockclient = TestCommon.GetMockRestClient(new Summary());
+ var client = TestCommon.GetClient(mockclient.Object);
+ client.ReadSummaryByKey("key1", new DateTime(2012, 3, 27), new DateTime(2012, 3, 28));
+
+ Expression> assertion = req => req.Method == Method.GET;
+ mockclient.Verify(cl => cl.Execute(It.Is(assertion)));
+ }
+
+ [Test]
+ public void RequestStartTime()
+ {
+ var mockclient = TestCommon.GetMockRestClient(new Summary());
+ var client = TestCommon.GetClient(mockclient.Object);
+ var start = new DateTime(2012, 6, 23);
+ var end = new DateTime(2012, 6, 24);
+
+ client.ReadSummaryByKey("testkey", start, end);
+
+ Expression> assertion = req => TestCommon.ContainsParameter(req.Parameters, "start", "2012-06-23T00:00:00.000-05:00");
+ mockclient.Verify(cl => cl.Execute(It.Is(assertion)));
+ }
+
+ [Test]
+ public void RequestEndTime()
+ {
+ var mockclient = TestCommon.GetMockRestClient(new Summary());
+ var client = TestCommon.GetClient(mockclient.Object);
+ var start = new DateTime(2012, 6, 23);
+ var end = new DateTime(2012, 6, 24);
+
+ client.ReadSummaryByKey("testkey", start, end);
+
+ Expression> assertion = req => TestCommon.ContainsParameter(req.Parameters, "end", "2012-06-24T00:00:00.000-05:00");
+ mockclient.Verify(cl => cl.Execute(It.Is(assertion)));
+ }
+
+ [Test]
+ public void RequestUrl()
+ {
+ var mockclient = TestCommon.GetMockRestClient(new Summary());
+ var client = TestCommon.GetClient(mockclient.Object);
+
+ client.ReadSummaryByKey("testkey", new DateTime(2012, 06, 23), new DateTime(2012, 06, 24));
+
+ mockclient.Verify(cl => cl.Execute(It.Is(req => req.Resource == "/{version}/series/{property}/{value}/data/summary/")));
+ mockclient.Verify(cl => cl.Execute(It.Is(req => TestCommon.ContainsParameter(req.Parameters, "property", "key"))));
+ mockclient.Verify(cl => cl.Execute(It.Is(req => TestCommon.ContainsParameter(req.Parameters, "value", "testkey"))));
+ }
+ }
+}
diff --git a/Client.Tests/TestCommon.cs b/Client.Tests/TestCommon.cs
index a7c98f5..ea0fce0 100644
--- a/Client.Tests/TestCommon.cs
+++ b/Client.Tests/TestCommon.cs
@@ -30,6 +30,13 @@ public static Client GetClient(RestClient restClient)
return restClient;
}
+ public static Mock GetMockRestClient(RestSharp.RestResponse res)
+ {
+ var restClient = new Mock();
+ restClient.Setup(cl => cl.Execute(It.IsAny())).Returns(res);
+ return restClient;
+ }
+
public static Mock GetMockRestClient()
{
var res = new RestSharp.RestResponse
diff --git a/Client/Client.cs b/Client/Client.cs
index 631b2fa..b91f9ca 100644
--- a/Client/Client.cs
+++ b/Client/Client.cs
@@ -1,7 +1,6 @@
+using Client.Json;
using Client.Model;
-using Newtonsoft.Json;
using RestSharp;
-using RestSharp.Deserializers;
using System;
using System.Collections.Generic;
using System.Net;
@@ -56,7 +55,7 @@ public Client(string key, string secret, string host = "api.tempo-db.com", int p
/// Executes the rest request, where no response is expected.
///
/// The request to be executed
- public void Execute(RestRequest request)
+ public IRestResponse Execute(RestRequest request)
{
RestClient client = GetRestClient();
IRestResponse response = client.Execute(request);
@@ -66,6 +65,7 @@ public void Execute(RestRequest request)
throw new Exception(string.Format("Service call failed with HTTP response [{0}].",
Enum.GetName(typeof (HttpStatusCode), response.StatusCode)));
}
+ return response;
}
///
@@ -96,6 +96,25 @@ public void Execute(RestRequest request)
return response.Data;
}
+ public RestRequest BuildRequest(string url, Method method, object body = null)
+ {
+ var request = new RestRequest {
+ Method = method,
+ Resource = url,
+ Timeout = DEFAULT_TIMEOUT_MILLIS,
+ RequestFormat = DataFormat.Json,
+ JsonSerializer = new JsonSerializer()
+ };
+ request.AddHeader("Accept-Encoding", "gzip,deflate");
+
+ if (body != null)
+ {
+ request.AddBody(body);
+ }
+
+ return request;
+ }
+
private RestClient GetRestClient()
{
if (_restClient == null)
@@ -103,7 +122,7 @@ private RestClient GetRestClient()
string protocol = _secure ? "https://" : "http://";
string portString = (_port == 80) ? "" : ":" + _port;
- string baseUrl = protocol + _host + portString + "/" + _version;
+ string baseUrl = protocol + _host + portString;
var client = new RestClient
{
@@ -127,11 +146,12 @@ private RestClient GetRestClient()
/// A Series
public Series CreateSeries(string key = "")
{
- const string url = "/series/";
+ const string url = "/{version}/series/";
var body = new Dictionary();
body.Add("key", key);
RestRequest request = BuildRequest(url, Method.POST, body);
+ request.AddUrlSegment("version", _version);
return Execute(request);
}
@@ -142,8 +162,9 @@ public Series CreateSeries(string key = "")
/// The updated Series
public Series UpdateSeries(Series series)
{
- const string url = "/series/id/{id}/";
+ const string url = "/{version}/series/id/{id}/";
RestRequest request = BuildRequest(url, Method.PUT, series);
+ request.AddUrlSegment("version", _version);
request.AddUrlSegment("id", series.Id);
return Execute(request);
}
@@ -154,11 +175,10 @@ public Series UpdateSeries(Series series)
/// A list of Series with the matching Key
public Series GetSeriesByKey(string key)
{
- const string url = "/series/key/{key}";
-
+ const string url = "/{version}/series/key/{key}";
RestRequest request = BuildRequest(url, Method.GET);
+ request.AddUrlSegment("version", _version);
request.AddUrlSegment("key", key);
-
return Execute(request);
}
@@ -168,11 +188,10 @@ public Series GetSeriesByKey(string key)
/// The Series that matches the specified Id
public Series GetSeriesById(string id)
{
- const string url = "/series/id/{id}";
-
+ const string url = "/{version}/series/id/{id}";
RestRequest request = BuildRequest(url, Method.GET);
+ request.AddUrlSegment("version", _version);
request.AddUrlSegment("id", id);
-
return Execute(request);
}
@@ -188,8 +207,9 @@ public List ListSeries(Filter filter = null)
filter = new Filter();
}
- const string url = "/series";
+ const string url = "/{version}/series/";
RestRequest request = BuildRequest(url, Method.GET);
+ request.AddUrlSegment("version", _version);
ApplyFilterToRequest(request, filter);
var result = Execute>(request);
return result;
@@ -217,8 +237,9 @@ public void WriteByKey(string seriesKey, IList data)
private void WriteDataPoints(string seriesProperty, string propertyValue, IList data)
{
- const string url = "/series/{property}/{value}/data/";
+ const string url = "/{version}/series/{property}/{value}/data/";
RestRequest request = BuildRequest(url, Method.POST, data);
+ request.AddUrlSegment("version", _version);
request.AddUrlSegment("property", seriesProperty);
request.AddUrlSegment("value", propertyValue);
Execute(request);
@@ -230,8 +251,9 @@ private void WriteDataPoints(string seriesProperty, string propertyValue, IList<
/// A BulkDataSet to write
public virtual void WriteBulkData(BulkDataSet dataSet)
{
- const string url = "/data/";
+ const string url = "/{version}/data/";
RestRequest request = BuildRequest(url, Method.POST, dataSet);
+ request.AddUrlSegment("version", _version);
Execute(request);
}
@@ -257,8 +279,9 @@ public void IncrementByKey(string seriesKey, IList data)
private void IncrementDataPoints(string seriesProperty, string propertyValue, IList data)
{
- const string url = "/series/{property}/{value}/increment/";
+ const string url = "/{version}/series/{property}/{value}/increment/";
RestRequest request = BuildRequest(url, Method.POST, data);
+ request.AddUrlSegment("version", _version);
request.AddUrlSegment("property", seriesProperty);
request.AddUrlSegment("value", propertyValue);
Execute(request);
@@ -270,8 +293,9 @@ private void IncrementDataPoints(string seriesProperty, string propertyValue, IL
/// A BulkDataSet to increments
public virtual void IncrementBulkData(BulkDataSet dataSet)
{
- const string url = "/increment/";
+ const string url = "/{version}/increment/";
RestRequest request = BuildRequest(url, Method.POST, dataSet);
+ request.AddUrlSegment("version", _version);
Execute(request);
}
@@ -299,36 +323,16 @@ public void DeleteByKey(string seriesKey, DateTime start, DateTime end)
private void DeleteDataPoints(string seriesProperty, string propertyValue, DateTime start, DateTime end)
{
- const string url = "/series/{property}/{value}/data";
+ const string url = "/{version}/series/{property}/{value}/data";
RestRequest request = BuildRequest(url, Method.DELETE);
+ request.AddUrlSegment("version", _version);
request.AddUrlSegment("property", seriesProperty);
request.AddUrlSegment("value", propertyValue);
- request.AddParameter(QueryStringParameter.Start, TempoDateTimeConvertor.ConvertDateTimeToString(start));
- request.AddParameter(QueryStringParameter.End, TempoDateTimeConvertor.ConvertDateTimeToString(end));
+ request.AddParameter(QueryStringParameter.Start, DateTimeConvertor.ConvertDateTimeToString(start));
+ request.AddParameter(QueryStringParameter.End, DateTimeConvertor.ConvertDateTimeToString(end));
Execute(request);
}
- private RestRequest BuildRequest(string url, Method method, object body = null)
- {
- var request = new RestRequest
- {
- Method = method,
- Resource = url,
- Timeout = DEFAULT_TIMEOUT_MILLIS,
- RequestFormat = DataFormat.Json,
- JsonSerializer = new JsonSerializer()
- };
-
- request.AddHeader("Accept-Encoding", "gzip,deflate");
-
- if (body != null)
- {
- request.AddBody(body);
- }
-
- return request;
- }
-
///
/// Reads a DataSet by id
///
@@ -362,8 +366,8 @@ public virtual DataSet ReadByKey(string seriesKey, DateTime start, DateTime end,
private DataSet ReadDataSet(string seriesProperty, string propertyValue, DateTime start, DateTime end,
string interval = null, string function = null)
{
- RestRequest request = BuildRequest("/series/{property}/{value}/data", Method.GET);
-
+ RestRequest request = BuildRequest("/{version}/series/{property}/{value}/data", Method.GET);
+ request.AddUrlSegment("version", _version);
request.AddUrlSegment("property", seriesProperty);
request.AddUrlSegment("value", propertyValue);
@@ -373,6 +377,85 @@ private DataSet ReadDataSet(string seriesProperty, string propertyValue, DateTim
return result;
}
+ ///
+ /// Queries a range of time series data for a series referenced by id. Returns a cursor (enumerator) over this data
+ /// which allows forward, one-time iteration.
+ ///
+ /// The id of the series
+ /// The start time of the range
+ /// The end time of the range
+ /// An interval for the rollup. (e.g. 1min, 15min, 1hour, 1day, 1month)
+ /// A function for the rollup. (e.g. min, max, sum, avg, stddev, count)
+ /// A Cursor
+ public virtual Cursor ReadCursorById(string seriesId, DateTime start, DateTime end, string interval=null,
+ string function=null)
+ {
+ return ReadCursor(SeriesProperty.Id, seriesId, start, end, interval, function);
+ }
+
+ ///
+ /// Queries a range of time series data for a series referenced by key. Returns a cursor (enumerator) over this data
+ /// which allows forward, one-time iteration.
+ ///
+ /// The id of the series
+ /// The start time of the range
+ /// The end time of the range
+ /// An interval for the rollup. (e.g. 1min, 15min, 1hour, 1day, 1month)
+ /// A function for the rollup. (e.g. min, max, sum, avg, stddev, count)
+ /// A Cursor
+ public virtual Cursor ReadCursorByKey(string seriesKey, DateTime start, DateTime end, string interval=null,
+ string function=null)
+ {
+ return ReadCursor(SeriesProperty.Key, seriesKey, start, end, interval, function);
+ }
+
+ private Cursor ReadCursor(string seriesProperty, string propertyValue, DateTime start, DateTime end,
+ string interval=null, string function=null)
+ {
+ RestRequest request = BuildRequest("/{version}/series/{property}/{value}/data/segment/", Method.GET);
+ request.AddUrlSegment("version", _version);
+ request.AddUrlSegment("property", seriesProperty);
+ request.AddUrlSegment("value", propertyValue);
+ AddReadParameters(request, start, end, interval, function);
+ IRestResponse response = Execute(request);
+
+ Segment segment = Segment.FromResponse(response);
+ SegmentEnumerator segments = new SegmentEnumerator(this, segment);
+ return new Cursor(segments);
+ }
+
+ ///
+ /// Reads a statistical summary for a range of data for a series referenced by id.
+ ///
+ /// The id of the series
+ /// The start time of the range
+ /// The end time of the range
+ public virtual Summary ReadSummaryById(string seriesId, DateTime start, DateTime end)
+ {
+ return ReadSummary(SeriesProperty.Id, seriesId, start, end);
+ }
+
+ ///
+ /// Reads a statistical summary for a range of data for a series referenced by key.
+ ///
+ /// The id of the series
+ /// The start time of the range
+ /// The end time of the range
+ public virtual Summary ReadSummaryByKey(string seriesKey, DateTime start, DateTime end)
+ {
+ return ReadSummary(SeriesProperty.Key, seriesKey, start, end);
+ }
+
+ private Summary ReadSummary(string seriesProperty, string propertyValue, DateTime start, DateTime end)
+ {
+ RestRequest request = BuildRequest("/{version}/series/{property}/{value}/data/summary/", Method.GET);
+ request.AddUrlSegment("version", _version);
+ request.AddUrlSegment("property", seriesProperty);
+ request.AddUrlSegment("value", propertyValue);
+ AddReadParameters(request, start, end);
+ return Execute(request);
+ }
+
///
/// Reads a list of DataSet by the provided filter and rolluped by the interval
///
@@ -385,8 +468,8 @@ private DataSet ReadDataSet(string seriesProperty, string propertyValue, DateTim
public virtual IList ReadMultipleSeries(DateTime start, DateTime end, Filter filter, string interval = null,
string function = null)
{
- RestRequest request = BuildRequest("/data/", Method.GET);
-
+ RestRequest request = BuildRequest("/{version}/data/", Method.GET);
+ request.AddUrlSegment("version", _version);
AddReadParameters(request, start, end, interval, function);
if (filter != null)
@@ -400,8 +483,8 @@ public virtual IList ReadMultipleSeries(DateTime start, DateTime end, F
private static void AddReadParameters(IRestRequest request, DateTime start, DateTime end, string interval = null,
string function = null)
{
- request.AddParameter(QueryStringParameter.Start, TempoDateTimeConvertor.ConvertDateTimeToString(start));
- request.AddParameter(QueryStringParameter.End, TempoDateTimeConvertor.ConvertDateTimeToString(end));
+ request.AddParameter(QueryStringParameter.Start, DateTimeConvertor.ConvertDateTimeToString(start));
+ request.AddParameter(QueryStringParameter.End, DateTimeConvertor.ConvertDateTimeToString(end));
if (!string.IsNullOrEmpty(interval))
{
diff --git a/Client/Json/DateTimeConverter.cs b/Client/Json/DateTimeConverter.cs
new file mode 100644
index 0000000..04bceff
--- /dev/null
+++ b/Client/Json/DateTimeConverter.cs
@@ -0,0 +1,26 @@
+using Newtonsoft.Json;
+using Newtonsoft.Json.Converters;
+using System;
+
+
+namespace Client.Json
+{
+ public class DateTimeConvertor : DateTimeConverterBase
+ {
+
+ public override void WriteJson(JsonWriter writer, object value, Newtonsoft.Json.JsonSerializer serializer)
+ {
+ writer.WriteValue(ConvertDateTimeToString(value));
+ }
+
+ public static string ConvertDateTimeToString(object value)
+ {
+ return ((DateTime)value).ToString("yyyy-MM-ddTHH:mm:ss.fffzzz");
+ }
+
+ public override object ReadJson(JsonReader reader, Type objectType, object existingValue, Newtonsoft.Json.JsonSerializer serializer)
+ {
+ return DateTime.Parse(reader.Value.ToString());
+ }
+ }
+}
diff --git a/Client/Json/JsonDeserializer.cs b/Client/Json/JsonDeserializer.cs
new file mode 100644
index 0000000..d01571e
--- /dev/null
+++ b/Client/Json/JsonDeserializer.cs
@@ -0,0 +1,20 @@
+using Newtonsoft.Json;
+using Newtonsoft.Json.Converters;
+using RestSharp;
+using RestSharp.Deserializers;
+
+
+namespace Client.Json
+{
+ public class JsonDeserializer : IDeserializer
+ {
+ public T Deserialize(IRestResponse response)
+ {
+ return JsonConvert.DeserializeObject(response.Content);
+ }
+
+ public string RootElement { get; set; }
+ public string Namespace { get; set; }
+ public string DateFormat { get; set; }
+ }
+}
diff --git a/Client/Json/JsonSerializer.cs b/Client/Json/JsonSerializer.cs
new file mode 100644
index 0000000..ffd99b3
--- /dev/null
+++ b/Client/Json/JsonSerializer.cs
@@ -0,0 +1,24 @@
+using Newtonsoft.Json;
+using RestSharp.Serializers;
+
+
+namespace Client.Json
+{
+ public class JsonSerializer : ISerializer
+ {
+ public JsonSerializer()
+ {
+ ContentType = "application/json";
+ }
+
+ public string Serialize(object obj)
+ {
+ return JsonConvert.SerializeObject(obj, new DateTimeConvertor());
+ }
+
+ public string RootElement { get; set; }
+ public string Namespace { get; set; }
+ public string DateFormat { get; set; }
+ public string ContentType { get; set; }
+ }
+}
diff --git a/Client/JsonSerializer.cs b/Client/JsonSerializer.cs
deleted file mode 100644
index 4b5820b..0000000
--- a/Client/JsonSerializer.cs
+++ /dev/null
@@ -1,59 +0,0 @@
-using Newtonsoft.Json;
-using Newtonsoft.Json.Converters;
-using RestSharp.Deserializers;
-using RestSharp.Serializers;
-using RestSharp;
-using System;
-
-
-namespace Client
-{
- public class JsonDeserializer : IDeserializer
- {
- public T Deserialize(IRestResponse response)
- {
- return JsonConvert.DeserializeObject(response.Content);
- }
-
- public string RootElement { get; set; }
- public string Namespace { get; set; }
- public string DateFormat { get; set; }
- }
-
- public class JsonSerializer : ISerializer
- {
- public JsonSerializer()
- {
- ContentType = "application/json";
- }
-
- public string Serialize(object obj)
- {
- return JsonConvert.SerializeObject(obj, new TempoDateTimeConvertor());
- }
-
- public string RootElement { get; set; }
- public string Namespace { get; set; }
- public string DateFormat { get; set; }
- public string ContentType { get; set; }
- }
-
- public class TempoDateTimeConvertor : DateTimeConverterBase
- {
-
- public override void WriteJson(JsonWriter writer, object value, Newtonsoft.Json.JsonSerializer serializer)
- {
- writer.WriteValue(ConvertDateTimeToString(value));
- }
-
- public static string ConvertDateTimeToString(object value)
- {
- return ((DateTime)value).ToString("yyyy-MM-ddTHH:mm:ss.fffzzz");
- }
-
- public override object ReadJson(JsonReader reader, Type objectType, object existingValue, Newtonsoft.Json.JsonSerializer serializer)
- {
- return DateTime.Parse(reader.Value.ToString());
- }
- }
-}
diff --git a/Client/Model/Cursor.cs b/Client/Model/Cursor.cs
new file mode 100644
index 0000000..f7cac3a
--- /dev/null
+++ b/Client/Model/Cursor.cs
@@ -0,0 +1,26 @@
+using System.Collections.Generic;
+
+
+namespace Client.Model
+{
+ public class Cursor
+ {
+ private SegmentEnumerator segments;
+
+ public Cursor(SegmentEnumerator segments)
+ {
+ this.segments = segments;
+ }
+
+ public IEnumerator GetEnumerator()
+ {
+ foreach(Segment segment in segments)
+ {
+ foreach(DataPoint dp in segment)
+ {
+ yield return dp;
+ }
+ }
+ }
+ }
+}
diff --git a/Client/Model/Segment.cs b/Client/Model/Segment.cs
new file mode 100644
index 0000000..f891253
--- /dev/null
+++ b/Client/Model/Segment.cs
@@ -0,0 +1,102 @@
+using Client.Json;
+using RestSharp;
+using System.Collections.Generic;
+
+
+namespace Client.Model
+{
+ public class Segment
+ {
+ private class SegmentJson
+ {
+ public List Data { get; set; }
+ public Dictionary Rollup { get; set; }
+ }
+
+ public IList Data { get; set; }
+ public string NextUrl { get; set; }
+
+ public Segment(IList data, string next)
+ {
+ Data = data;
+ NextUrl = next;
+ }
+
+ /// For now, build the Segment by passing in a RestResponse.
+ /// This should be handled by a deserializer in the future
+ public static Segment FromResponse(IRestResponse response)
+ {
+ /// Deserialize the data
+ JsonDeserializer deserializer = new JsonDeserializer();
+ var result = deserializer.Deserialize(response);
+ List data = result.Data;
+
+ /// Get the next link from the Link header
+ Parameter header = null;
+ foreach(Parameter h in response.Headers)
+ {
+ if(h.Name.ToLower().Equals("link"))
+ {
+ header = h;
+ break;
+ }
+ }
+
+ Dictionary> links = new Dictionary>();
+ if(header != null)
+ {
+ List> l = ParseHeaderLinks(header.Value as string);
+ foreach(Dictionary link in l)
+ {
+ string key = link.ContainsKey("rel") ? link["rel"] : link["url"];
+ links.Add(key, link);
+ }
+ }
+
+ Dictionary next = new Dictionary();
+ string nextUrl = null;
+ if(links.TryGetValue("next", out next))
+ {
+ next.TryGetValue("url", out nextUrl);
+ }
+
+ return new Segment(data, nextUrl);
+ }
+
+ public IEnumerator GetEnumerator()
+ {
+ foreach(DataPoint dp in Data)
+ {
+ yield return dp;
+ }
+ }
+
+ private static List> ParseHeaderLinks(string header)
+ {
+ char[] replaceChars = {' ', '\'', '"'};
+ char[] replaceUrlChars = {'<', '>', ' ', '\'', '"'};
+ List> links = new List>();
+ foreach(string val in header.Split(','))
+ {
+ string[] items = val.Split(';');
+ if(items.Length > 0)
+ {
+ string url = items[0];
+ string parameters = items.Length > 1 ? items[1] : "";
+ Dictionary link = new Dictionary();
+ link.Add("url", url.Trim(replaceUrlChars));
+ foreach(string param in parameters.Split(';'))
+ {
+ string[] keys = param.Split('=');
+ if(keys.Length < 1) break;
+ string key = keys[0];
+ string item = keys[1];
+ link.Add(key.Trim(replaceChars).ToLower(), item.Trim(replaceChars));
+ }
+ links.Add(link);
+ }
+ }
+ return links;
+ }
+ }
+}
diff --git a/Client/Model/SegmentEnumerator.cs b/Client/Model/SegmentEnumerator.cs
new file mode 100644
index 0000000..cab334c
--- /dev/null
+++ b/Client/Model/SegmentEnumerator.cs
@@ -0,0 +1,30 @@
+using RestSharp;
+using System.Collections.Generic;
+
+
+namespace Client.Model
+{
+ public class SegmentEnumerator
+ {
+ private Segment segment;
+ private Client client;
+
+ public SegmentEnumerator(Client client, Segment segment)
+ {
+ this.client = client;
+ this.segment = segment;
+ }
+
+ public IEnumerator GetEnumerator()
+ {
+ yield return segment;
+ while(segment.NextUrl != null)
+ {
+ var request = client.BuildRequest(segment.NextUrl, Method.GET);
+ var response = client.Execute(request);
+ segment = Segment.FromResponse(response);
+ yield return segment;
+ }
+ }
+ }
+}
diff --git a/Client/Model/Summary.cs b/Client/Model/Summary.cs
new file mode 100644
index 0000000..9204a89
--- /dev/null
+++ b/Client/Model/Summary.cs
@@ -0,0 +1,14 @@
+using System;
+using System.Collections.Generic;
+
+
+namespace Client.Model
+{
+ ///
+ /// Respresents summary statistics from a time range of a series. The Summary table contains
+ /// statistics for the time range (sum, mean, min, max, count, etc.)
+ ///
+ public class Summary : Dictionary
+ {
+ }
+}
diff --git a/Client/TempoClient.csproj b/Client/TempoClient.csproj
index b2eaed3..4b56490 100644
--- a/Client/TempoClient.csproj
+++ b/Client/TempoClient.csproj
@@ -13,7 +13,7 @@
v4.0
512
..\
- true
+ false
true
@@ -49,16 +49,22 @@
-
+
+
+
+
+
+
+
diff --git a/Makefile b/Makefile
index 7a351a0..4774afd 100644
--- a/Makefile
+++ b/Makefile
@@ -1,4 +1,4 @@
-.PHONY: compile compile-test clean clean-build clean-test
+.PHONY: compile compile-test update update-build update-test clean clean-build clean-test
compile:
xbuild Client/TempoClient.csproj
@@ -6,6 +6,14 @@ compile:
compile-test: compile
xbuild Client.Tests/Client.Tests.csproj
+update-build:
+ xbuild Client/TempoClient.csproj /t:RestorePackages
+
+update-test:
+ xbuild Client.Tests/Client.Tests.csproj /t:RestorePackages
+
+update: update-build update-test
+
test: compile-test
mono packages/NUnit.Runners.2.6.1/tools/nunit-console.exe Client.Tests/bin/Debug/Client.Tests.dll
diff --git a/README.md b/README.md
index 38aa01b..73da68b 100644
--- a/README.md
+++ b/README.md
@@ -17,9 +17,10 @@ Stores the session information for authenticating and accessing TempoDB. Your ap
also allows you to specify the hostname, port, and protocol (http or https). This is used if you are on a private cluster.
#### Constructor
-``
+```
Client(key, secret, host, port, version, secure, restClient)
-``
+```
+
* key - api key (string)
* secret - api secret (string)
* host - [Optional] hostname for cluster (string)
@@ -27,7 +28,7 @@ Client(key, secret, host, port, version, secure, restClient)
* secure - [Optional] protocol to use (true=https, false=http)
* restClient - [Optional] rest client to use. Mainly used for testing.
-```csharp
+``` csharp
var client = new Client("my-key", "my-secret");
```
@@ -83,6 +84,14 @@ and a statistics summary table. The Summary table contains statistics for the ti
* Data - datapoints ( List )
* Summary - a summary table of statistics for the queried range ( Dictionary )
+## Cursor
+Represents an enumerable of DataPoints. This allows you to iterate over a very large number of datapoints for a single series without loading the entire result into memory. This class is a result of the ReadCursorBy* client functions.
+### Members
+* None, the object is enumerable
+
+## Summary
+Represents a table of statistics for a rangle of data. This is dictionary of string->double. Values in the dictionary include mean, sum, minimum, maximum, standard deviation, and count.
+
## Bulk Writes
The Bulk classes exist to facilitate using the bulk write endpoint, which provides the ability to write to multiple series per timestamp.
@@ -125,6 +134,10 @@ public void DeleteById(string seriesId, DateTime start, DateTime end)
public void DeleteByKey(string seriesKey, DateTime start, DateTime end)
public virtual DataSet ReadById(string seriesId, DateTime start, DateTime end, string interval = null, string function = null)
public virtual DataSet ReadByKey(string seriesKey, DateTime start, DateTime end, string interval = null, string function = null)
+public virtual Cursor ReadCursorById(string seriesId, DateTime start, DateTime end, string interval=null, string function=null)
+public virtual Cursor ReadCursorByKey(string seriesKey, DateTime start, DateTime end, string interval=null, string function=null)
+public virtual Summary ReadSummaryById(string seriesId, DateTime start, DateTime end)
+public virtual Summary ReadSummaryByKey(string seriesKey, DateTime start, DateTime end)
```
## CreateSeries(string key="")
@@ -208,7 +221,6 @@ filter.AddAttribute("key", "val");
var series = client.ListSeries(filter);
```
-
## UpdateSeries(Series series)
Updates a series. The series id is taken from the passed-in series object. Currently, only tags and attributes can be
modified. The easiest way to use this method is through a read-modify-write cycle.
@@ -221,6 +233,7 @@ The updated Series
### Example
The following example reads the list of series with key *test1* and replaces the tags with *tag3*.
+
```csharp
var client = new Client("api-key", "api-secret");
@@ -282,7 +295,7 @@ var resultsRolledUp = client.ReadById("38268c3b231f1266a392931e15e99231", new Da
var resultsRaw = client.ReadById("38268c3b231f1266a392931e15e99231", new DateTime(2012, 1, 1), new DateTime(2012, 1, 2));
```
-## ReadByKey(string seriesId, DateTime start, DateTime end, string interval = null, string function = null)
+## ReadByKey(string seriesKey, DateTime start, DateTime end, string interval = null, string function = null)
Gets a DataSet by series key. The key, start, and end times are required. The same rollup rules apply as for the ReadByKey
@@ -307,8 +320,98 @@ var client = new Client("api-key", "api-secret");
var data = client.ReadByKey("my-key", new DateTime(2012, 1, 1), new DateTime(2012, 2, 1), IntervalParameters.Days(1), FoldingFunction.Min);
```
-## WriteById(string seriesId, IList data)
+##ReadCursorById(string seriesId, DateTime start, DateTime end, string interval = null, string function = null)
+Gets a Cursor for the specified start/end times for a series referenced by id. The interval parameter allows you to specify a rollup period. For example,
+"1hour" will roll the data up on the hour using the provided function. The function parameter specifies the folding function
+to use while rolling the data up. The available folding functions and intervals are listed under the ReadById section above.
+
+### Parameters
+* seriesId - the seriesId to include (string)
+* start - start time for the query (DateTime)
+* end - end time for the query (DateTime)
+* interval - the rollup interval (string)
+* function - the rollup folding function (string)
+
+### Returns
+A Cursor over DataPoints. This is a one-time, forward enumerable over a range of datapoints.
+
+### Example
+
+The following example returns a Cursor from 2012-01-01 to 2012-01-02 for the series with id "38268c3b231f1266a392931e15e99231",
+with the maximum value for each hour as well as the raw data.
+
+```csharp
+var client = new Client("api-key", "api-secret");
+
+var cursor = client.ReadCursorById("38268c3b231f1266a392931e15e99231", new DateTime(2012, 1, 1), new DateTime(2012, 1, 2), IntervalParameter.Hour(1), FoldingFunction.Max);
+var cursorRaw = client.ReadCursorById("38268c3b231f1266a392931e15e99231", new DateTime(2012, 1, 1), new DateTime(2012, 1, 2));
+```
+
+## ReadCursorByKey(string seriesKey, DateTime start, DateTime end, string interval = null, string function = null)
+
+
+Gets a Cursor for the specified start/end times for a series referenced by key. The key, start, and end times are required. The interval parameter allows you to specify a rollup period. For example,
+"1hour" will roll the data up on the hour using the provided function. The function parameter specifies the folding function
+to use while rolling the data up. The available folding functions and intervals are listed under the ReadById section above.
+
+### Parameters
+* seriesKey - key for the series to read from (string)
+* start - start time for the query (DateTime)
+* end - end time for the query (DateTime)
+* interval - the rollup interval (string)
+* function - the rollup folding function (string)
+
+### Returns
+A Cursor over DataPoints. This is a one-time, forward enumerable over a range of datapoints.
+
+### Example
+
+The following example reads data for the series with id "my-key" from 2012-01-01 to 2012-02-01 and
+returns a minimum datapoint per day.
+```csharp
+var client = new Client("api-key", "api-secret");
+var cursor = client.ReadCursorByKey("my-key", new DateTime(2012, 1, 1), new DateTime(2012, 2, 1), IntervalParameters.Days(1), FoldingFunction.Min);
+```
+
+## ReadSummaryById(string seriesId, DateTime start, DateTime end)
+Gets a Summary for for a range of data for a series referenced by id. The key, start, and end times are required.
+
+### Parameters
+* seriesId - id for the series to read from (string)
+* start - start time for the query (DateTime)
+* end - end time for the query (DateTime)
+
+### Returns
+A Summary object.
+
+### Example
+
+The following example reads a summary object for the series with id "38268c3b231f1266a392931e15e99231" from 2012-01-01 to 2012-02-01.
+```csharp
+var client = new Client("api-key", "api-secret");
+var summary = client.ReadSummaryById("38268c3b231f1266a392931e15e99231", new DateTime(2012, 1, 1), new DateTime(2012, 2, 1));
+```
+
+## ReadSummaryByKey(string seriesKey, DateTime start, DateTime end)
+Gets a Summary for for a range of data for a series referenced by key. The key, start, and end times are required.
+
+### Parameters
+* seriesKey - key for the series to read from (string)
+* start - start time for the query (DateTime)
+* end - end time for the query (DateTime)
+
+### Returns
+A Summary object.
+
+### Example
+The following example reads a summary object for the series with key "my-key" from 2012-01-01 to 2012-02-01.
+```csharp
+var client = new Client("api-key", "api-secret");
+var summary = client.ReadSummaryByKey("my-key", new DateTime(2012, 1, 1), new DateTime(2012, 2, 1));
+```
+
+## WriteById(string seriesId, IList data)
Writes datapoints to the specified series. The series id and a list of DataPoints are required.
### Parameters