/ToMigrate/Raven.Tests.Counters/SmugglerTests.cs

https://github.com/fitzchak/ravendb · C# · 394 lines · 332 code · 60 blank · 2 comment · 54 complexity · 6a43ab9805648563863cc89f0b115329 MD5 · raw file

  1. using System;
  2. using System.IO;
  3. using System.Linq;
  4. using System.Net;
  5. using System.Threading;
  6. using System.Threading.Tasks;
  7. using Raven.Abstractions.Connection;
  8. using Raven.Abstractions.Data;
  9. using Raven.Abstractions.Smuggler;
  10. using Raven.Abstractions.Util;
  11. using Raven.Client.Counters;
  12. using Raven.Database.Extensions;
  13. using Raven.Database.Smuggler;
  14. using Xunit;
  15. namespace Raven.Tests.Counters
  16. {
  17. public class SmugglerTests : RavenBaseCountersTest
  18. {
  19. private const string CounterDumpFilename = "testCounter.counterdump";
  20. public SmugglerTests()
  21. {
  22. IOExtensions.DeleteFile(CounterDumpFilename);
  23. IOExtensions.DeleteDirectory(CounterDumpFilename); //counters incremental export creates folder with incremental dump files
  24. }
  25. private const string goodApikey = "test/ThisIsMySecret";
  26. private const string badApikey = "test2/ThisIsNotMySecret";
  27. [Fact]
  28. public async Task Smuggler_export_with_ApiKey_should_work()
  29. {
  30. using (var server = GetNewServer(port: 8010,configureConfig: ConfigureServerForAuth))
  31. {
  32. using (var counterStore = NewRemoteCountersStore("storeX", ravenServer: server))
  33. {
  34. await counterStore.IncrementAsync("G", "C");
  35. await counterStore.DecrementAsync("G", "C2");
  36. }
  37. using (var counterStore = NewRemoteCountersStore("storeX", ravenServer: server))
  38. {
  39. ConfigureApiKey(server.SystemDatabase, "test", "ThisIsMySecret", counterStore.Name, true);
  40. var smugglerApi = new SmugglerCounterApi();
  41. Assert.DoesNotThrow(() => AsyncHelpers.RunSync(() =>
  42. smugglerApi.ExportData(new SmugglerExportOptions<CounterConnectionStringOptions>
  43. {
  44. ToFile = CounterDumpFilename,
  45. From = ConnectionStringTo(counterStore, goodApikey)
  46. })));
  47. }
  48. }
  49. }
  50. //note: smuggler import/export requires admin access to <system> database
  51. [Fact]
  52. public async Task Smuggler_import_with_ApiKey_should_work()
  53. {
  54. using (var serverA = GetNewServer(port: 8010,configureConfig: ConfigureServerForAuth))
  55. using (var serverB = GetNewServer(port: 8011, configureConfig: ConfigureServerForAuth))
  56. {
  57. using (var counterStoreA = NewRemoteCountersStore("storeX", ravenServer: serverA))
  58. {
  59. await counterStoreA.IncrementAsync("G", "C");
  60. await counterStoreA.DecrementAsync("G", "C2");
  61. }
  62. using (var counterStoreA = NewRemoteCountersStore("storeX", ravenServer: serverA))
  63. using (var counterStoreB = NewRemoteCountersStore("storeY", ravenServer: serverB))
  64. {
  65. ConfigureApiKey(serverA.SystemDatabase, "test", "ThisIsMySecret", counterStoreA.Name, true);
  66. ConfigureApiKey(serverA.SystemDatabase, "test2", "ThisIsNotMySecret", counterStoreA.Name + "FooBar", true);
  67. ConfigureApiKey(serverB.SystemDatabase, "test", "ThisIsMySecret", counterStoreB.Name, true);
  68. ConfigureApiKey(serverB.SystemDatabase, "test2", "ThisIsNotMySecret", counterStoreB.Name + "FooBar", true);
  69. var smugglerApi = new SmugglerCounterApi();
  70. var e = Assert.Throws<ErrorResponseException>(() => AsyncHelpers.RunSync(() =>
  71. smugglerApi.ExportData(new SmugglerExportOptions<CounterConnectionStringOptions>
  72. {
  73. ToFile = CounterDumpFilename,
  74. From = ConnectionStringTo(counterStoreA, badApikey)
  75. })));
  76. Assert.Equal(HttpStatusCode.Forbidden, e.StatusCode);
  77. Assert.DoesNotThrow(() => AsyncHelpers.RunSync(() =>
  78. smugglerApi.ExportData(new SmugglerExportOptions<CounterConnectionStringOptions>
  79. {
  80. ToFile = CounterDumpFilename,
  81. From = ConnectionStringTo(counterStoreA, goodApikey)
  82. })));
  83. e = Assert.Throws<ErrorResponseException>(() => AsyncHelpers.RunSync(() =>
  84. smugglerApi.ImportData(new SmugglerImportOptions<CounterConnectionStringOptions>
  85. {
  86. FromFile = CounterDumpFilename,
  87. To = ConnectionStringTo(counterStoreB, badApikey)
  88. })));
  89. Assert.Equal(HttpStatusCode.Forbidden, e.StatusCode);
  90. Assert.DoesNotThrow(() => AsyncHelpers.RunSync(() =>
  91. smugglerApi.ImportData(new SmugglerImportOptions<CounterConnectionStringOptions>
  92. {
  93. FromFile = CounterDumpFilename,
  94. To = ConnectionStringTo(counterStoreB, goodApikey)
  95. })));
  96. }
  97. }
  98. }
  99. [Fact]
  100. public void SmugglerExport_with_error_in_stream_should_fail_gracefully()
  101. {
  102. using (var counterStore = NewRemoteCountersStore("store"))
  103. using (var stream = new FailingStream())
  104. {
  105. var smugglerApi = new SmugglerCounterApi();
  106. Assert.Throws<FailingStreamException>(() => AsyncHelpers.RunSync(() => smugglerApi.ExportData(new SmugglerExportOptions<CounterConnectionStringOptions>
  107. {
  108. ToStream = stream,
  109. From = ConnectionStringTo(counterStore)
  110. })));
  111. }
  112. }
  113. //make sure that if a stream throws exception during import it comes through
  114. [Fact]
  115. public void SmugglerImport_with_error_in_stream_should_fail_gracefully()
  116. {
  117. using (var counterStore = NewRemoteCountersStore("store"))
  118. using (var stream = new FailingStream())
  119. {
  120. var smugglerApi = new SmugglerCounterApi();
  121. Assert.Throws<FailingStreamException>(() => AsyncHelpers.RunSync(() => smugglerApi.ImportData(new SmugglerImportOptions<CounterConnectionStringOptions>
  122. {
  123. FromStream = stream,
  124. To = new CounterConnectionStringOptions
  125. {
  126. Url = counterStore.Url,
  127. CounterStoreId = counterStore.Name
  128. }
  129. })));
  130. }
  131. }
  132. [Fact]
  133. public async Task SmugglerExport_to_file_should_not_fail()
  134. {
  135. using (var counterStore = NewRemoteCountersStore("store"))
  136. {
  137. await counterStore.ChangeAsync("g1", "c1", 5);
  138. await counterStore.IncrementAsync("g1", "c1");
  139. await counterStore.IncrementAsync("g1", "c2");
  140. await counterStore.IncrementAsync("g2", "c1");
  141. var smugglerApi = new SmugglerCounterApi();
  142. await smugglerApi.ExportData(new SmugglerExportOptions<CounterConnectionStringOptions>
  143. {
  144. ToFile = CounterDumpFilename,
  145. From = ConnectionStringTo(counterStore)
  146. });
  147. var fileInfo = new FileInfo(CounterDumpFilename);
  148. Assert.True(fileInfo.Exists);
  149. Assert.True(fileInfo.Length > 0);
  150. }
  151. }
  152. [Fact]
  153. public async Task SmugglerExport_incremental_to_file_should_not_fail()
  154. {
  155. using (var counterStore = NewRemoteCountersStore("store"))
  156. {
  157. await counterStore.ChangeAsync("g1", "c1", 5);
  158. await counterStore.IncrementAsync("g1", "c1");
  159. await counterStore.IncrementAsync("g1", "c2");
  160. await counterStore.IncrementAsync("g2", "c1");
  161. var smugglerApi = new SmugglerCounterApi();
  162. smugglerApi.Options.Incremental = true;
  163. await smugglerApi.ExportData(new SmugglerExportOptions<CounterConnectionStringOptions>
  164. {
  165. ToFile = CounterDumpFilename,
  166. From = ConnectionStringTo(counterStore)
  167. });
  168. await counterStore.IncrementAsync("g1", "c2");
  169. await counterStore.DecrementAsync("g2", "c1");
  170. await smugglerApi.ExportData(new SmugglerExportOptions<CounterConnectionStringOptions>
  171. {
  172. ToFile = CounterDumpFilename,
  173. From = ConnectionStringTo(counterStore)
  174. });
  175. var incrementalFolder = new DirectoryInfo(CounterDumpFilename);
  176. Assert.True(incrementalFolder.Exists);
  177. var dumpFiles = incrementalFolder.GetFiles();
  178. Assert.Equal(3, dumpFiles.Length);
  179. Assert.True(dumpFiles.All(x=>x.Length>0));
  180. }
  181. }
  182. [Fact]
  183. public async Task SmugglerImport_incremental_from_file_should_work()
  184. {
  185. using (var counterStore = NewRemoteCountersStore("storeToExport"))
  186. {
  187. await counterStore.ChangeAsync("g1", "c1", 5);
  188. await counterStore.IncrementAsync("g1", "c2");
  189. var smugglerApi = new SmugglerCounterApi
  190. {
  191. Options = { Incremental = true }
  192. };
  193. await smugglerApi.ExportData(new SmugglerExportOptions<CounterConnectionStringOptions>
  194. {
  195. ToFile = CounterDumpFilename,
  196. From = ConnectionStringTo(counterStore)
  197. });
  198. await counterStore.IncrementAsync("g", "c");
  199. await counterStore.IncrementAsync("g1", "c2");
  200. await smugglerApi.ExportData(new SmugglerExportOptions<CounterConnectionStringOptions>
  201. {
  202. ToFile = CounterDumpFilename,
  203. From = ConnectionStringTo(counterStore)
  204. });
  205. await counterStore.ChangeAsync("g", "c", -3);
  206. await smugglerApi.ExportData(new SmugglerExportOptions<CounterConnectionStringOptions>
  207. {
  208. ToFile = CounterDumpFilename,
  209. From = ConnectionStringTo(counterStore)
  210. });
  211. }
  212. using (var counterStore = NewRemoteCountersStore("storeToImportTo"))
  213. {
  214. var smugglerApi = new SmugglerCounterApi()
  215. {
  216. Options = {Incremental = true}
  217. };
  218. await smugglerApi.ImportData(new SmugglerImportOptions<CounterConnectionStringOptions>
  219. {
  220. FromFile = CounterDumpFilename,
  221. To = ConnectionStringTo(counterStore)
  222. });
  223. var summary = await counterStore.Admin.GetCountersByStorage(counterStore.Name);
  224. Assert.Equal(3, summary.Count);//sanity check
  225. Assert.NotNull(summary.SingleOrDefault(x => x.CounterName == "c1" && x.GroupName == "g1"));
  226. Assert.NotNull(summary.SingleOrDefault(x => x.CounterName == "c2" && x.GroupName == "g1"));
  227. Assert.NotNull(summary.SingleOrDefault(x => x.CounterName == "c" && x.GroupName == "g"));
  228. Assert.Equal(5, summary.First(x => x.CounterName == "c1" && x.GroupName == "g1").Total);
  229. Assert.Equal(3, summary.First(x => x.CounterName == "c2" && x.GroupName == "g1").Total);
  230. Assert.Equal(-2, summary.First(x => x.CounterName == "c" && x.GroupName == "g").Total);
  231. }
  232. }
  233. [Fact]
  234. public async Task SmugglerImport_from_file_should_work()
  235. {
  236. using (var counterStore = NewRemoteCountersStore("storeToExport"))
  237. {
  238. await counterStore.ChangeAsync("g1", "c1", 5);
  239. await counterStore.IncrementAsync("g1", "c1");
  240. await counterStore.IncrementAsync("g1", "c2");
  241. await counterStore.DecrementAsync("g2", "c1");
  242. var smugglerApi = new SmugglerCounterApi();
  243. await smugglerApi.ExportData(new SmugglerExportOptions<CounterConnectionStringOptions>
  244. {
  245. ToFile = CounterDumpFilename,
  246. From = ConnectionStringTo(counterStore)
  247. });
  248. }
  249. using (var counterStore = NewRemoteCountersStore("storeToImportTo"))
  250. {
  251. var smugglerApi = new SmugglerCounterApi();
  252. await smugglerApi.ImportData(new SmugglerImportOptions<CounterConnectionStringOptions>
  253. {
  254. FromFile = CounterDumpFilename,
  255. To = ConnectionStringTo(counterStore)
  256. });
  257. var summary = await counterStore.Admin.GetCountersByStorage(counterStore.Name);
  258. Assert.Equal(3, summary.Count); //sanity check
  259. Assert.NotNull(summary.SingleOrDefault(x => x.CounterName == "c1" && x.GroupName == "g1"));
  260. Assert.NotNull(summary.SingleOrDefault(x => x.CounterName == "c2" && x.GroupName == "g1"));
  261. Assert.NotNull(summary.SingleOrDefault(x => x.CounterName == "c1" && x.GroupName == "g2"));
  262. Assert.Equal(6, summary.First(x => x.CounterName == "c1" && x.GroupName == "g1").Total);//change + inc
  263. Assert.Equal(1, summary.First(x => x.CounterName == "c2" && x.GroupName == "g1").Total);
  264. Assert.Equal(-1, summary.First(x => x.CounterName == "c1" && x.GroupName == "g2").Total);
  265. }
  266. }
  267. [Fact]
  268. public async Task SmugglerBetween_should_work()
  269. {
  270. using (var source = NewRemoteCountersStore("source"))
  271. using (var target = NewRemoteCountersStore("target"))
  272. {
  273. await source.ChangeAsync("g1", "c1", 5);
  274. await source.ChangeAsync("g1", "c1",-3);
  275. await source.IncrementAsync("g1", "c2");
  276. await source.ChangeAsync("g2", "c1",4);
  277. var smugglerApi = new SmugglerCounterApi();
  278. await smugglerApi.Between(new SmugglerBetweenOptions<CounterConnectionStringOptions>
  279. {
  280. From = ConnectionStringTo(source),
  281. To = ConnectionStringTo(target)
  282. });
  283. var summary = await target.Admin.GetCountersByStorage(target.Name);
  284. Assert.Equal(3, summary.Count); //sanity check
  285. Assert.NotNull(summary.SingleOrDefault(x => x.CounterName == "c1" && x.GroupName == "g1"));
  286. Assert.NotNull(summary.SingleOrDefault(x => x.CounterName == "c2" && x.GroupName == "g1"));
  287. Assert.NotNull(summary.SingleOrDefault(x => x.CounterName == "c1" && x.GroupName == "g2"));
  288. Assert.Equal(2, summary.First(x => x.CounterName == "c1" && x.GroupName == "g1").Total);
  289. Assert.Equal(1, summary.First(x => x.CounterName == "c2" && x.GroupName == "g1").Total);
  290. Assert.Equal(4, summary.First(x => x.CounterName == "c1" && x.GroupName == "g2").Total);
  291. }
  292. }
  293. private CounterConnectionStringOptions ConnectionStringTo(ICounterStore counterStore, string overrideApiKey = null)
  294. {
  295. return new CounterConnectionStringOptions
  296. {
  297. ApiKey = overrideApiKey ?? counterStore.Credentials.ApiKey,
  298. Credentials = counterStore.Credentials.Credentials,
  299. CounterStoreId = counterStore.Name,
  300. Url = counterStore.Url
  301. };
  302. }
  303. private class FailingStreamException : Exception
  304. {
  305. }
  306. private class FailingStream : MemoryStream
  307. {
  308. public override Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
  309. {
  310. throw new FailingStreamException();
  311. }
  312. public override void WriteByte(byte value)
  313. {
  314. throw new FailingStreamException();
  315. }
  316. public override void Write(byte[] buffer, int offset, int count)
  317. {
  318. throw new FailingStreamException();
  319. }
  320. public override int Read(byte[] buffer, int offset, int count)
  321. {
  322. throw new FailingStreamException();
  323. }
  324. public override int ReadByte()
  325. {
  326. throw new FailingStreamException();
  327. }
  328. public override Task<int> ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
  329. {
  330. throw new FailingStreamException();
  331. }
  332. }
  333. }
  334. }