2using System.Collections.Concurrent;
3using System.Collections.Generic;
4using System.Diagnostics;
5using System.Globalization;
8using System.Reflection;
10using System.Threading;
22using Microsoft.VisualStudio.TestTools.UnitTesting;
27using TestCategory =
NUnit.Framework.CategoryAttribute;
35 private const string TypeName =
"LargeDataUpload";
37 #region String Test Properties
44 #endregion String Test Properties
46 #region File Test Properties
56 #endregion File Test Properties
66 Console.WriteLine(
"The Test_LargeDataUpload.SampleCatalogFilePath references a " +
67 "location that does not exist in the current context. Tests that rely on " +
68 "this resource will not be able to run. (" +
ex.Message +
")");
72 #region Helper Methods
76 char separator = Path.DirectorySeparatorChar;
79 string basePath = Path.GetDirectoryName(
Assembly.GetExecutingAssembly().CodeBase);
83 return new Uri(
basePath.Replace(
"#",
"%23").Replace(
"file:",
"")).LocalPath;
85 return new Uri(
basePath.Replace(
"#",
"%23")).LocalPath;
102 $"\nOriginal Contents:\n{original}\nRetrieved Contents:\n{retrieved}");
103 Debug.WriteLine(
$"Asserted that the retrieved file contents matched the original:\n{retrieved}");
114 #endregion Helper Methods
116 #region Simple String Tests
147 Debug.WriteLine(
$"Expected contents are:\n{expectedContents}" +
148 $"\nTotal Content Length: {expectedContents.Length}");
154 #endregion Simple String Tests
156 #region Reference Existing Files
162 Assert.Inconclusive(
"RUN_OFFLINE = true");
165 newCatalog.data_file =
other.data_file;
176 Skip.
Indefinitely(
"ARE-3694 - Setting data reference on PUT does not kick off validation.");
180 Assert.IsNull(posted.data_file);
181 posted.data_file = other.data_file;
182 posted = posted.Put();
183 posted = posted.PollUntilReady(Samples.DataPollingOptions);
184 Assert.AreEqual(posted.status, TaskStatus.Success);
185 AssertContentsMatch(other.data.Get(), posted.data);
188 #endregion Reference Existing Files
190 #region Simple File Tests
219 () => data.LargeFileUpload(
"bad path")));
268 #endregion Simple File Tests
270 #region Upload Conflict Tests
271 #region With Compression
281 new Parameters(enable_compression:
true, handle_existing_upload_strategy:
284 "a large upload is already in progress. To attempt to resume or cancel " +
285 "the existing upload session, set the 'handle_existing_upload_strategy' " +
286 "parameter appropriately.",
ex.
Message));
298 new Parameters(enable_compression:
true, handle_existing_upload_strategy:
312 new Parameters(enable_compression:
true, handle_existing_upload_strategy:
328 new Parameters(enable_compression:
true, handle_existing_upload_strategy:
333 () => data.
Patch(
"some_data", 1024),
337 Assert.AreEqual(data.
status.
Get().status.IsProcessingComplete(),
true);
341 Assert.AreEqual(
e.ServerError.message,
"Data has been uploaded and processed successfully.");
347 object[] parameters =
new object[] {
349 Encoding.ASCII.GetBytes(
"some_data"),
366 new Parameters(enable_compression:
true, handle_existing_upload_strategy:
380 new Parameters(enable_compression:
true, handle_existing_upload_strategy:
395 new Parameters(enable_compression:
true, handle_existing_upload_strategy:
398 "file of different size. Prior file size: {0} This file size: {1}",
402 #endregion With Compression
404 #region Without Compression
417 "a large upload is already in progress. To attempt to resume or cancel " +
418 "the existing upload session, set the 'handle_existing_upload_strategy' " +
419 "parameter appropriately.",
ex.
Message));
491 "file of different size. Prior file size: {0} This file size: {1}",
495 #endregion Without Compression
507 ex =>
Assert.AreEqual(
"Cannot upload data for this resource because " +
508 "existing data has already been successfully uploaded.",
ex.Message));
523 new Parameters(handle_existing_upload_strategy:
527 #endregion Upload Conflict Tests
529 #region Asynchronous Upload
530 #region Helper Methods
533 #region Async Test Properties
538 public Exception
Error {
get;
set; }
542 #endregion Async Test Properties
544 #region Async Test Delegates
554 result => Response = result;
555 #endregion Async Test Delegates
573 enable_compression:
false,
574 commit_polling_options:
Samples.DataPollingOptions,
599 Debug.Write(
"\nProgress Updates: ");
603 long uploaded = status.bytes_uploaded ?? -1;
615 #endregion Helper Methods
617 #region Asynchronous Upload Tests
673 data.LargeFileUpload_Async(
"bad path");
676 #endregion Asynchronous Upload Tests
677 #endregion Asynchronous Upload
679 #region Encoding Tests
694 [
TestMethod, TestCategory(TypeName), TestCategory(
"Skipped")]
703 RootSamplesCsvPath +
@"event_catalog_encodings\event_catalog_data_unicodebigendian.csv"
711 Assert.Inconclusive(
"RUN_OFFLINE = true");
725 "\nError: " +
ex +
"\n\n");
731 "One or more unsupported encodings encountered:\n" +
735 #endregion Encoding Tests
737 #region Binary Upload
746 Console.WriteLine(
$"{actionName} took {(now - startTime).TotalSeconds} seconds.");
752 [
Obsolete(
"ARE-5226 Remove support for Binary YELT Loss Set format. ")]
756 Assert.Inconclusive(
"RUN_OFFLINE = true");
758 const int rows = 500000;
767 description =
"Minimal Event Catalog",
769 }.Post(
"\"Event Id\",\"Rate\"\n" + String.Join(
"\n",
775 description =
"Sample Binary YELT",
785 commit_polling_options:
Samples.DataPollingOptions,
803 (r.NextDouble() * 100000
d).ToString(
"0.##") +
"\n");
806 $"Generating YELT with {rows:#,###} rows.");
837 Console.WriteLine(
$"\nCompressed File size: {bytes} bytes, {megabytes:0.00}MiB");
838 Console.WriteLine(
$"Upload Speed: {(int)(bytes / elapsed.TotalSeconds)} bytes/s " +
839 $"({(megabytes / elapsed.TotalSeconds):0.00} MiBps)");
844 Console.WriteLine(
$"\nOriginal File size: {bytes} bytes, {megabytes:0.00}MiB");
847 Console.WriteLine(
$"Effective Throughput: {(int)(bytes / elapsed.TotalSeconds)} " +
848 $"bytes/s ({(megabytes / elapsed.TotalSeconds):0.00} MiBps)\n");
851 Console.WriteLine(
$"Throughput including server time: " +
852 $"{(int)(bytes / endToEndElapsed.TotalSeconds)} bytes/s " +
853 $"({(megabytes / endToEndElapsed.TotalSeconds):0.00} MiBps)\n");
856 $"Async upload appears to have failed: {lastUpdate?.status} - {async_state.Error}");
858 $"Async upload appears to have never failed: {async_state.Error}");
860 $"Async upload appears to have never completed: {lastUpdate?.status}");
871 commit_polling_options:
Samples.DataPollingOptions,
877 copy.data.LargeStreamUpload_Async(
881 Console.WriteLine(
$"- {overhead.TotalSeconds:0.0000} " +
882 "(Overhead for any upload determined by uploading a teeny tiny file)");
884 Console.WriteLine(
$"= {elapsed.TotalSeconds:0.0000} Adjusted Upload-Only Time");
887 Console.WriteLine(
$"\nAdjusted Throughput: {(int)(bytes / elapsed.TotalSeconds)} " +
888 $"bytes/s ({(megabytes / elapsed.TotalSeconds):0.00} MiBps)");
889 Console.WriteLine(
"Adjusted Throughput is an optimistic measure of the C# " +
890 "client's capacity to push volumes of data to the server by ignoring " +
891 "fixed overhead and subsequent validation performance of the server.\n");
897 [
Obsolete(
"ARE-5226 Remove support for Binary YELT Loss Set format. ")]
901 Assert.Inconclusive(
"RUN_OFFLINE = true");
918 binary_yelt_options = Parameters.BinaryYELTUploadOptions.AutomaticCompressionOnly
926 $"Upload appears to have failed: {status.commit_error}");
929 $"not completed successfully: {binaryYelt.status} - {binaryYelt.status_message}");
934 [
Obsolete(
"ARE-5226 Remove support for Binary YELT Loss Set format. ")]
938 Assert.Inconclusive(
"RUN_OFFLINE = true");
957 binary_yelt_options = Parameters.BinaryYELTUploadOptions.None
965 $"Upload appears to have failed: {status.commit_error}");
968 $"not completed successfully: {binaryYelt.status} - {binaryYelt.status_message}");
991 "following 5 reads in a row - yet CanTake is still true. Infinite loop avoided.");
998 [
Obsolete(
"ARE-5226 Remove support for Binary YELT Loss Set format. ")]
1002 Assert.Inconclusive(
"RUN_OFFLINE = true");
1017 binary_yelt_options = Parameters.BinaryYELTUploadOptions.None
1021 copy =
binaryYelt.DeepCopy().Change(r => r.data_file,
null).Post();
1024 byte[] buffer =
new byte[4096];
1028 while ((count =
downloadStream.Read(buffer, 0, buffer.Length)) != 0)
1029 ms.Write(buffer, 0, count);
1039 copy =
binaryYelt.DeepCopy().Change(r => r.data_file,
null).Post();
1054 [
Obsolete(
"ARE-5226 Remove support for Binary YELT Loss Set format. ")]
1058 Assert.Inconclusive(
"RUN_OFFLINE = true");
1062 yelt.Post(
"1,0,1.5,542345.543\n" +
1063 "2,98765,-123.456,-9999.9999\n" +
1066 #endregion Binary Upload
1068 #region Stream of indeterminate Length
1078 public override bool CanSeek =>
false;
1079 public override bool CanWrite =>
false;
1087 public override void Flush() { }
1091 public override int Read(
byte[] buffer,
int offset,
int count)
1096 for (
int i = offset;
i < offset + count;
i++)
1097 buffer[
i] =
i % 1000 == 0 ? (
byte)(
char)10 : (
byte)(
char)(44 + (
i ^ 13) % (58 - 48));
1109 Assert.Inconclusive(
"RUN_OFFLINE = true");
1117 },
ex =>
Assert.AreEqual(
"The uploaded file failed validation " +
1118 "with the following message: CSV input error: Event ID column not found.",
ex.Message));
1127 private byte[] _leftOver;
1138 public override bool CanSeek =>
false;
1139 public override bool CanWrite =>
false;
1157 public override void Flush() { }
1161 public override int Read(
byte[] buffer,
int offset,
int count)
1166 const string yeltFormat =
"{0},{1},{2:f2},{3:f2}\n";
1171 if (_leftOver !=
null)
1176 if (count < _leftOver.Length)
1178 byte[]
leftOverleft =
new byte[_leftOver.Length - count];
1197 nextRow =
"Event Id,Trial Id,Day,Loss\n";
1208 _rng.NextDouble() * 100000
d );
1235 [
Obsolete(
"ARE-5226 Remove support for Binary YELT Loss Set format. ")]
1239 Assert.Inconclusive(
"RUN_OFFLINE = true");
1250 Console.WriteLine(
$"Upload of {yeltStream.RowsGenerated} row YELT " +
1251 $"took {elapsedSeconds:0.0} seconds " +
1252 $"({(yeltStream.RowsGenerated / elapsedSeconds):0} rows per second).");
1253 Console.WriteLine(
$"Total bytes (uncompressed): {yeltStream.BytesReturned}.");
1254 Console.WriteLine(
"Effective Throughput: " +
1255 $"{(yeltStream.BytesReturned / 1.049e+6 / elapsedSeconds):0.00} MiB per second.");
1258 #endregion Stream of indeterminate Length
1260 #region StreamProducers
1281 data.BytesReturned +
" bytes requested from the stream, which " +
1282 "exceeds the set number of bytes to read of " +
bytes_to_read);
1286 Assert.Fail(
"The stream took longer than " +
timeoutMs +
"ms to respond.");
1290 "be reflected in the total number of bytes returned.");
1292 "be reflected in the total number of bytes requested from the stream.");
1295 #endregion StreamProducers
Create a test class that takes care of setting the server URL and cleaning up after each unit test.
Exposes the various sample CSV files as strings.
static string Event_Catalog_Data
static string YELTLossSet_10Trials_ForBinary
Exposes sample resource objects, with built-in methods for injecting dependencies.
static readonly PollingOptions DataPollingOptions
Polling options to use when uploading a data file.
IInjectableResource< YELTLossSet > LossSet_YELTLossSet
IInjectableResource< EventCatalog > EventCatalog
static void MethodIsAllowed(Action request, string methodName, bool methodAllowed=true)
Wrap a request in a tryGet with some formatting for testing purposes.
Retrieve settings from environment variables if they exist, or the project settings file otherwise.
static bool RUN_OFFLINE
Controls whether tests that normally require a connection to the server should be allowed to try to r...
Generic Unit test implementations that will test REST methods on arbitrary resources.
Class used in unit tests to mark tests as skipped by using Assert.Inconclusive() method.
static void Indefinitely(string ticket=null)
Skip the specified test.
A custom exception class that includes the RestSharp.IRestResponse that generated the exception,...
Describes an endpoint off of some types of resources from which an associated "large data file" can b...
SubResource< LargeDataUpload.StatusResponse > status
The endpoint at which the status of the data can be determined.
void Patch(string data, long bytesOffset, int? timeout=null, IEnumerable< Parameter > requestParameters=null)
Performs a PATCH of part of this object's data at this endpoint.
Describes a collection of resources which can be listed.
T Get(IEnumerable< Parameter > parameters=null, int? timeout=null)
Performs a GET request a at this endpoint.
API methods / requests made available to the user.
static void PollUntil(Func< bool > request, AnalyzeRe.PollingOptions pollingOptions=null)
Poll the specified request until it returns true.
Representation of an event catalog. The event catalog may cover multiple region/perils,...
Parameters to be used in a Large Upload operation.
Converts a YELT CSV data into a specified format.
Indicates that an exception occurred inside of a buffered producer thread.
Produces a BlockingCollection of buffered bytes asynchronously which can be consumed on some other th...
Exception raised when the commit process fails.
Converts buffered bytes to strings.
Parameters to be used in a Large Data Upload operation.
Indicates the status of a data endpoint.
string commit_error
If the processing of the file failed, the error message reported by the server.
Indicates that a large upload could not take place because an existing large upload session is alread...
Large Data Upload Utilities.
static MemoryStream GetStringStream(string input)
Generate a byte stream from a string which can be used in the LargeStreamUpload methods.
Representation of a loss set with an associated year-event-loss table.
DataType
The format of the data uploaded against this YELT.
Determines the behaviour of the API when automatically retrying a request whose result is not yet rea...
T Unposted
The unPOSTed resource definition.
T Posted
The posted resource, ready to be referenced.
@ Error
Indicates that there was an error while determining the authentication status.
HandleUploadInSessionStrategy
Behaviour to use if an existing upload is already in progress for an endpoint.
@ CancelPriorUpload
If any prior upload in progress is encountered, it will be deleted before beginning anew with the cur...
@ RaiseError
If any prior upload in progress is encountered, do not interfere and raise an UploadInProgress except...
@ AttemptResume
If any prior upload in progress is encountered, attempt to resume the upload starting at the offset w...
The structure containing an array of bytes and integer indicating the number of bytes in the array th...
@ currency
Reinstatement values represent a fixed dollar amount.
TaskStatus
The status of a data upload which may be in progress.