Skip to content

Commit

Permalink
more consistent error handling. Exceptions for timeouts and timeouts …
Browse files Browse the repository at this point in the history
…at 10seconds
  • Loading branch information
kareem613 committed Mar 8, 2014
1 parent c8611a2 commit 0141ba1
Show file tree
Hide file tree
Showing 3 changed files with 88 additions and 39 deletions.
62 changes: 50 additions & 12 deletions SharpSpark.Tests/SparkClientTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -90,49 +90,87 @@ public void GivenClientWhenGetVarDoubleExpectDouble()
}

[TestMethod]
[ExpectedException(typeof(SparkDeviceException),"Variable not found")]
//[ExpectedException(typeof(SparkDeviceException),"Variable not found")]
public void GivenInvalidVariableExpectErrorVariableNotFound()
{
SparkVariableResult result = client.GetVariable("thisdoesnotexist");
try{
SparkVariableResult result = client.GetVariable("thisdoesnotexist");
}
catch (SparkDeviceException spex)
{
Assert.AreEqual("Variable not found", spex.Message);
}
}

[TestMethod]
[ExpectedException(typeof(SparkDeviceException), "Function not found")]
//[ExpectedException(typeof(SparkDeviceException), "Function not found")]
public void GivenInvalidFunctionExpectErrorFunctionNotFound()
{
SparkFunctionResult result = client.ExecuteFunction("thisdoesnotexist");
try{
SparkFunctionResult result = client.ExecuteFunction("thisdoesnotexist");
}
catch (SparkDeviceException spex)
{
Assert.AreEqual("Function not found", spex.Message);
}
}

[TestMethod]
[ExpectedException(typeof(SparkApiException), "invalid_grant")]
//[ExpectedException(typeof(SparkApiException), "invalid_grant")]
public void GivenInvalidAccessTokenExpectErrorInvalidGrant()
{
var badClient = new SparkClient("badtoken", "");
SparkFunctionResult result = badClient.ExecuteFunction("doesn't matter");
try
{
SparkFunctionResult result = badClient.ExecuteFunction("doesn't matter");
}
catch (SparkApiException spex)
{
Assert.AreEqual("invalid_grant", spex.Message);
}
}

[TestMethod]
[ExpectedException(typeof(SparkApiException), "Permission Denied")]
//[ExpectedException(typeof(SparkApiException), "Permission Denied")]
public void GivenInvalidDeviceIdExpectErrorPermissionDenied()
{
var badClient = new SparkClient(client.AccessToken, "badid");
SparkFunctionResult result = badClient.ExecuteFunction("doesn't matter");
try {
SparkFunctionResult result = badClient.ExecuteFunction("doesn't matter");
}
catch (SparkApiException spex)
{
Assert.AreEqual("Permission Denied", spex.Message);
}
}

[Ignore]//This test only passes if the device is offline
[TestMethod]
[ExpectedException(typeof(SparkDeviceException), "Timed out.")]
//[ExpectedException(typeof(SparkDeviceException), "Timed out.")]
public void GivenOfflineDeviceFunctionExpectErrorTimedOut()
{
SparkFunctionResult result = client.ExecuteFunction("returnOne");
try {
SparkFunctionResult result = client.ExecuteFunction("returnOne");
}
catch (SparkDeviceException spex)
{
Assert.AreEqual("Too slow to respond or offline", spex.Message);
}
}

[Ignore]//This test only passes if the device is offline
[TestMethod]
[ExpectedException(typeof(SparkDeviceException), "Timed out.")]
//[ExpectedException(typeof(SparkDeviceException), "Timed out.")]
public void GivenOfflineDeviceVariableExpectErrorTimedOut()
{
SparkVariableResult result = client.GetVariable("var0");
try
{
SparkVariableResult result = client.GetVariable("var0");
}
catch (SparkDeviceException spex)
{
Assert.AreEqual("Too slow to respond or offline", spex.Message);
}
}

}
Expand Down
7 changes: 4 additions & 3 deletions SharpSpark/CloudApiHttpClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ namespace Maybe5.SharpSpark
{
class CloudApiHttpClient
{
const int TIMEOUT_SECONDS = 10;
public string AccessToken { get; private set; }
public string DeviceId { get; private set; }

Expand All @@ -17,7 +18,7 @@ public CloudApiHttpClient(string accessToken, string deviceId)

public string GetRawResultForGetDevices()
{
using (var client = new HttpClient())
using (var client = new HttpClient() { Timeout = new TimeSpan(0, 0, TIMEOUT_SECONDS) })
{
var result = client.GetAsync(String.Format("https://api.spark.io/v1/devices?access_token={0}", AccessToken)).Result;
result.EnsureSuccessStatusCode();
Expand All @@ -27,7 +28,7 @@ public string GetRawResultForGetDevices()

public HttpResponseMessage GetRawResultForGet(string variableName)
{
using (var client = new HttpClient())
using (var client = new HttpClient() { Timeout = new TimeSpan(0, 0, TIMEOUT_SECONDS) })
{
return client.GetAsync(String.Format("https://api.spark.io/v1/devices/{0}/{1}?access_token={2}", DeviceId, variableName, AccessToken)).Result;

Expand All @@ -37,7 +38,7 @@ public HttpResponseMessage GetRawResultForGet(string variableName)

public HttpResponseMessage GetRawResultForPost(string functionKey, string[] args)
{
using (var client = new HttpClient())
using (var client = new HttpClient() { Timeout = new TimeSpan(0, 0, TIMEOUT_SECONDS) })
{
var content = new FormUrlEncodedContent(new[]
{
Expand Down
58 changes: 34 additions & 24 deletions SharpSpark/SparkClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ public string DeviceId
return CloudApiClient.DeviceId;
}
}

private CloudApiHttpClient CloudApiClient { get; set; }

public SparkClient(string accessToken, string deviceId)
Expand All @@ -37,30 +37,19 @@ public SparkClient(string accessToken, string deviceId)
public SparkVariableResult GetVariable(string variableName)
{
var result = CloudGet(variableName);
if(result.HasError)
{
throw new SparkDeviceException(result.Error,result);
}
return result;
}

public SparkFunctionResult ExecuteFunction(string functionKey, params string[] args)
{
var result = CloudPost(functionKey, args);
if (result.HasErrors)
{
if(API_ERROR_MESSAGES.Contains(result.ErrorResult.Error))
throw new SparkApiException(result.ErrorResult.Error, result.ErrorResult);

throw new SparkDeviceException(result.ErrorResult.Error, result.ErrorResult);
}
return result;
}

public T GetVariableReturnValue<T>(string variableName)
{
var result = GetVariable(variableName);
return (T)Convert.ChangeType(result.Result.ToString(),typeof(T));
return (T)Convert.ChangeType(result.Result.ToString(), typeof(T));
}

public int ExecuteFunctionReturnValue(string functionKey, params string[] args)
Expand All @@ -71,24 +60,45 @@ public int ExecuteFunctionReturnValue(string functionKey, params string[] args)

private SparkVariableResult CloudGet(string variableName)
{
var response = CloudApiClient.GetRawResultForGet(variableName);
var rawContent = response.Content.ReadAsStringAsync().Result;
if (!response.IsSuccessStatusCode || rawContent.StartsWith("{\n \"error\":"))
try
{
return new SparkVariableResult() { ErrorResult = JsonConvert.DeserializeObject<SparkError>(rawContent) };
var response = CloudApiClient.GetRawResultForGet(variableName);
var rawContent = response.Content.ReadAsStringAsync().Result;
if (!response.IsSuccessStatusCode || rawContent.StartsWith("{\n \"error\":"))
{
var sparkError = JsonConvert.DeserializeObject<SparkError>(rawContent);
throw new SparkDeviceException(sparkError.Error, sparkError);
}
return JsonConvert.DeserializeObject<SparkVariableResult>(rawContent);
}
catch (AggregateException)
{
var sparkError = new SparkError() { Error = "Too slow to respond or offline" };
throw new SparkDeviceException(sparkError.Error, sparkError);
}
return JsonConvert.DeserializeObject<SparkVariableResult>(rawContent);
}

private SparkFunctionResult CloudPost(string functionKey, string[] args)
{
var response = CloudApiClient.GetRawResultForPost(functionKey, args);
var rawContent = response.Content.ReadAsStringAsync().Result;
if (!response.IsSuccessStatusCode || rawContent.StartsWith("{\n \"error\":"))
try
{
var response = CloudApiClient.GetRawResultForPost(functionKey, args);
var rawContent = response.Content.ReadAsStringAsync().Result;
if (!response.IsSuccessStatusCode || rawContent.StartsWith("{\n \"error\":"))
{
var sparkError = JsonConvert.DeserializeObject<SparkError>(rawContent);
if (API_ERROR_MESSAGES.Contains(sparkError.Error))
throw new SparkApiException(sparkError.Error, sparkError);

throw new SparkDeviceException(sparkError.Error, sparkError);
}
return JsonConvert.DeserializeObject<SparkFunctionResult>(rawContent);
}
catch (AggregateException)
{
return new SparkFunctionResult() { ErrorResult = JsonConvert.DeserializeObject<SparkError>(rawContent) };
var sparkError = new SparkError() { Error = "Too slow to respond or offline" };
throw new SparkDeviceException(sparkError.Error, sparkError);
}
return JsonConvert.DeserializeObject<SparkFunctionResult>(rawContent);
}

public SparkDevice GetDevice()
Expand All @@ -97,7 +107,7 @@ public SparkDevice GetDevice()
var rawContent = response.Content.ReadAsStringAsync().Result;
if (!response.IsSuccessStatusCode || rawContent.StartsWith("{\n \"error\":"))
{
var sparkError = JsonConvert.DeserializeObject<SparkError>(rawContent);
var sparkError = JsonConvert.DeserializeObject<SparkError>(rawContent);
throw new SparkApiException(sparkError.Error);
}
return JsonConvert.DeserializeObject<SparkDevice>(rawContent);
Expand Down

0 comments on commit 0141ba1

Please sign in to comment.