Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 32 additions & 27 deletions SimpleStorage/Client/SimpleStorageClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,34 +6,39 @@

namespace Client
{
public class SimpleStorageClient : ISimpleStorageClient
{
private readonly IEnumerable<string> endpoints;
public class SimpleStorageClient : ISimpleStorageClient
{
private readonly IEnumerable<string> endpoints;

public SimpleStorageClient(params string[] endpoints)
{
if (endpoints == null || !endpoints.Any())
throw new ArgumentException("Empty endpoints!", "endpoints");
this.endpoints = endpoints;
}
public SimpleStorageClient(params string[] endpoints)
{
if (endpoints == null || !endpoints.Any())
throw new ArgumentException("Empty endpoints!", "endpoints");
this.endpoints = endpoints;
}

public void Put(string id, Value value)
{
var putUri = endpoints.First() + "api/values/" + id;
using (var client = new HttpClient())
using (var response = client.PutAsJsonAsync(putUri, value).Result)
response.EnsureSuccessStatusCode();
}
public void Put(string id, Value value)
{
var putUri = endpoints.ElementAt(getShardNumber(id, endpoints.Count())) + "api/values/" + id;
using (var client = new HttpClient())
using (var response = client.PutAsJsonAsync(putUri, value).Result)
response.EnsureSuccessStatusCode();
}

public Value Get(string id)
{
var requestUri = endpoints.First() + "api/values/" + id;
using (var client = new HttpClient())
using (var response = client.GetAsync(requestUri).Result)
{
response.EnsureSuccessStatusCode();
return response.Content.ReadAsAsync<Value>().Result;
}
}
}
public Value Get(string id)
{
var requestUri = endpoints.ElementAt(getShardNumber(id, endpoints.Count())) + "api/values/" + id;
using (var client = new HttpClient())
using (var response = client.GetAsync(requestUri).Result) {
response.EnsureSuccessStatusCode();
return response.Content.ReadAsAsync<Value>().Result;
}
}

static int getShardNumber(string id, int count)
{
return (Math.Abs(id.GetHashCode()) % count);
}

}
}
2 changes: 1 addition & 1 deletion SimpleStorage/SimpleStorage.Tests/FuctionalTestBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,4 @@ public virtual void SetUp()
container.Configure(c => c.For<IStorage>().Use(storage));
}
}
}
}
85 changes: 85 additions & 0 deletions SimpleStorage/SimpleStorage.Tests/Sharding/Task1Tests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using Client;
using Domain;
using NUnit.Framework;

namespace SimpleStorage.Tests.Sharding
{
[TestFixture]
public class Task1Tests
{
private static readonly string endpoint1 = string.Format ("http://127.0.0.1:{0}/", 16000);
private static readonly string endpoint2 = string.Format ("http://127.0.0.1:{0}/", 16001);
private static readonly string endpoint3 = string.Format ("http://127.0.0.1:{0}/", 16002);
private readonly string[] endpoints = { endpoint1, endpoint2, endpoint3 };
private SimpleStorageClient client;

[SetUp]
public void SetUp ()
{
client = new SimpleStorageClient (endpoints);

using (var httpClient = new HttpClient ())
foreach (var endpoint in endpoints) {
using (var response =
httpClient.PostAsync (endpoint + "api/admin/removeAllData", new ByteArrayContent (new byte[0]))
.Result)
Assert.That (response.StatusCode, Is.EqualTo (HttpStatusCode.NoContent));
}
}

[Test]
public void Sharding_EachShard_ShouldNotContainAllData ()
{


Assert.That (GetAll (endpoint1).ToArray (), Has.Length.LessThan (100));
Assert.That (GetAll (endpoint2).ToArray (), Has.Length.LessThan (100));
Assert.That (GetAll (endpoint3).ToArray (), Has.Length.LessThan (100));
}

[Test]
public void Sharding_AllShards_ShouldContainSomeData ()
{
for (var i = 0; i < 100; i++)
client.Put (Guid.NewGuid ().ToString (), new Value { Content = "content" });

Assert.That (GetAll (endpoint1).ToArray (), Has.Length.GreaterThan (0));
Assert.That (GetAll (endpoint2).ToArray (), Has.Length.GreaterThan (0));
Assert.That (GetAll (endpoint3).ToArray (), Has.Length.GreaterThan (0));
}

[Test]
public void Sharding_Always_ShouldSaveAllData ()
{
var items = new List<KeyValuePair<string, Value>> ();
for (var i = 0; i < 100; i++) {
var id = Guid.NewGuid ().ToString ();
var value = new Value { Content = "content" };
items.Add (new KeyValuePair<string, Value> (id, value));
client.Put (id, value);
}

foreach (var item in items) {
var actual = client.Get (item.Key);
Assert.That (actual.Content, Is.EqualTo (item.Value.Content));
Assert.That (actual.IsDeleted, Is.EqualTo (item.Value.IsDeleted));
Assert.That (actual.Revision, Is.EqualTo (item.Value.Revision));
}
}

private IEnumerable<ValueWithId> GetAll (string endpoint)
{
var requestUri = endpoint + "api/admin/getAllLocalData";
using (var httpClient = new HttpClient ())
using (var response = httpClient.GetAsync (requestUri).Result) {
response.EnsureSuccessStatusCode ();
return response.Content.ReadAsAsync<IEnumerable<ValueWithId>> ().Result;
}
}
}
}
78 changes: 78 additions & 0 deletions SimpleStorage/SimpleStorage.Tests/Sharding/Task2Tests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using Client;
using Domain;
using NUnit.Framework;

namespace SimpleStorage.Tests.Sharding
{
[TestFixture]
public class Task2Tests
{
private static readonly string endpoint1 = string.Format("http://127.0.0.1:{0}/", 16000);
private static readonly string endpoint2 = string.Format("http://127.0.0.1:{0}/", 16001);
private static readonly string endpoint3 = string.Format("http://127.0.0.1:{0}/", 16002);

[SetUp]
public void SetUp()
{
using (var httpClient = new HttpClient())
foreach (var endpoint in new[] { endpoint1, endpoint2, endpoint3 })
{
using (var response =
httpClient.PostAsync(endpoint + "api/admin/removeAllData", new ByteArrayContent(new byte[0]))
.Result)
Assert.That(response.StatusCode, Is.EqualTo(HttpStatusCode.NoContent));
}
}

[Test]
public void Sharding_AllShards_ShouldContainSomeData()
{
var client = new SimpleStorageClient(endpoint1);
for (var i = 0; i < 100; i++)
client.Put(Guid.NewGuid().ToString(), new Value { Content = "content" });

Assert.That(GetAll(endpoint1).ToArray(), Has.Length.GreaterThan(0));
Assert.That(GetAll(endpoint2).ToArray(), Has.Length.GreaterThan(0));
Assert.That(GetAll(endpoint3).ToArray(), Has.Length.GreaterThan(0));
}

[Test]
public void Sharding_Always_ShouldReadAllData()
{
var client = new SimpleStorageClient(endpoint1);
var items = new List<KeyValuePair<string, Value>>();
for (var i = 0; i < 100; i++)
{
var id = Guid.NewGuid().ToString();
var value = new Value { Content = "content" };
items.Add(new KeyValuePair<string, Value>(id, value));
client.Put(id, value);
}

foreach (var item in items)
foreach (var endpoint in new[] { endpoint1, endpoint2, endpoint3 })
{
var actual = new SimpleStorageClient(endpoint).Get(item.Key);
Assert.That(actual.Content, Is.EqualTo(item.Value.Content));
Assert.That(actual.IsDeleted, Is.EqualTo(item.Value.IsDeleted));
Assert.That(actual.Revision, Is.EqualTo(item.Value.Revision));
}
}

private IEnumerable<ValueWithId> GetAll(string endpoint)
{
var requestUri = endpoint + "api/admin/getAllLocalData";
using (var httpClient = new HttpClient())
using (var response = httpClient.GetAsync(requestUri).Result)
{
response.EnsureSuccessStatusCode();
return response.Content.ReadAsAsync<IEnumerable<ValueWithId>>().Result;
}
}
}
}
90 changes: 90 additions & 0 deletions SimpleStorage/SimpleStorage.Tests/Sharding/Task3Tests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using Client;
using Domain;
using NUnit.Framework;

namespace SimpleStorage.Tests.Sharding
{
[TestFixture]
public class Task3Tests
{
private static readonly string endpoint1 = string.Format("http://127.0.0.1:{0}/", 16000);
private static readonly string endpoint2 = string.Format("http://127.0.0.1:{0}/", 16001);
private static readonly string endpoint3 = string.Format("http://127.0.0.1:{0}/", 16002);
private readonly string[] endpoints = {endpoint1, endpoint2, endpoint3};
private SimpleStorageClient client;

[SetUp]
public void SetUp()
{
client = new SimpleStorageClient(endpoints);

using (var httpClient = new HttpClient())
foreach (var endpoint in endpoints)
{
using (var response =
httpClient.PostAsync(endpoint + "api/admin/removeAllData", new ByteArrayContent(new byte[0]))
.Result)
Assert.That(response.StatusCode, Is.EqualTo(HttpStatusCode.NoContent));
}
}

[Test]
public void Sharding_EachShard_ShouldNotContainAllData()
{
for (var i = 0; i < 100; i++)
client.Put(Guid.NewGuid().ToString(), new Value {Content = "content"});

Assert.That(GetAll(endpoint1).ToArray(), Has.Length.LessThan(100));
Assert.That(GetAll(endpoint2).ToArray(), Has.Length.LessThan(100));
Assert.That(GetAll(endpoint3).ToArray(), Has.Length.LessThan(100));
}

[Test]
public void Sharding_AllShards_ShouldContainSomeData()
{
for (var i = 0; i < 100; i++)
client.Put(Guid.NewGuid().ToString(), new Value {Content = "content"});

Assert.That(GetAll(endpoint1).ToArray(), Has.Length.GreaterThan(0));
Assert.That(GetAll(endpoint2).ToArray(), Has.Length.GreaterThan(0));
Assert.That(GetAll(endpoint3).ToArray(), Has.Length.GreaterThan(0));
}

[Test]
public void Sharding_Always_ShouldSaveAllData()
{
var items = new List<KeyValuePair<string, Value>>();
for (var i = 0; i < 100; i++)
{
var id = Guid.NewGuid().ToString();
var value = new Value {Content = "content"};
items.Add(new KeyValuePair<string, Value>(id, value));
client.Put(id, value);
}

foreach (var item in items)
{
var actual = client.Get(item.Key);
Assert.That(actual.Content, Is.EqualTo(item.Value.Content));
Assert.That(actual.IsDeleted, Is.EqualTo(item.Value.IsDeleted));
Assert.That(actual.Revision, Is.EqualTo(item.Value.Revision));
}
}

private IEnumerable<ValueWithId> GetAll(string endpoint)
{
var requestUri = endpoint + "api/admin/getAllLocalData";
using (var httpClient = new HttpClient())
using (var response = httpClient.GetAsync(requestUri).Result)
{
response.EnsureSuccessStatusCode();
return response.Content.ReadAsAsync<IEnumerable<ValueWithId>>().Result;
}
}
}
}
1 change: 0 additions & 1 deletion SimpleStorage/SimpleStorage.Tests/ShardingTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
namespace SimpleStorage.Tests
{
[TestFixture]
[Ignore]
public class ShardingTests
{
private const int port1 = 15000;
Expand Down
24 changes: 15 additions & 9 deletions SimpleStorage/packages/repositories.config
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<repositories>
<repository path="..\Client\packages.config" />
<repository path="..\Coordinator\packages.config" />
<repository path="..\Core\packages.config" />
<repository path="..\Domain.Tests\packages.config" />
<repository path="..\SimpleStorage.Tests\packages.config" />
<repository path="..\SimpleStorage\packages.config" />
</repositories>
<?xml version="1.0" encoding="utf-8"?>
<repositories>
<repository path="../Client/packages.config" />
<repository path="../Coordinator/packages.config" />
<repository path="../Core/packages.config" />
<repository path="../Domain.Tests/packages.config" />
<repository path="../SimpleStorage.Tests/packages.config" />
<repository path="../SimpleStorage/packages.config" />
<repository path="..\Client\packages.config" />
<repository path="..\Coordinator\packages.config" />
<repository path="..\Core\packages.config" />
<repository path="..\Domain.Tests\packages.config" />
<repository path="..\SimpleStorage.Tests\packages.config" />
<repository path="..\SimpleStorage\packages.config" />
</repositories>