public void ExoticCoverage() { Executing.This(() => TeaFile <int> .Create((string)null)).Should().Throw <ArgumentNullException>(); Executing.This(() => TeaFile <int> .Create((string)null, "contento", null)).Should().Throw <ArgumentNullException>(); Executing.This(() => TeaFile <int> .Create((string)null, "a", null, true)).Should().Throw <ArgumentNullException>(); Executing.This(() => TeaFile <int> .Create((Stream)null, "a", null, true)).Should().Throw <ArgumentNullException>(); Executing.This(() => TeaFile <int> .Create((Stream)null)).Should().Throw <ArgumentNullException>(); Executing.This(() => TeaFile <int> .Create((Stream)null, "contento", null)).Should().Throw <ArgumentNullException>(); Executing.This(() => TeaFile <int> .OpenRead((Stream)null)).Should().Throw <ArgumentNullException>(); Executing.This(() => TeaFile <int> .OpenRead((Stream)null, ItemDescriptionElements.None)).Should().Throw <ArgumentNullException>(); Executing.This(() => TeaFile <int> .OpenRead((string)null)).Should().Throw <ArgumentNullException>(); Executing.This(() => TeaFile <int> .OpenRead((string)null, ItemDescriptionElements.None)).Should().Throw <ArgumentNullException>(); Executing.This(() => TeaFile <int> .OpenWrite((Stream)null)).Should().Throw <ArgumentNullException>(); Executing.This(() => TeaFile <int> .OpenWrite((Stream)null, ItemDescriptionElements.None)).Should().Throw <ArgumentNullException>(); Executing.This(() => TeaFile <int> .OpenWrite((string)null)).Should().Throw <ArgumentNullException>(); Executing.This(() => TeaFile <int> .OpenWrite((string)null, ItemDescriptionElements.None)).Should().Throw <ArgumentNullException>(); Executing.This(() => TeaFile <int> .Append(null)).Should().Throw <ArgumentNullException>(); Executing.This(() => TeaFile <int> .Append(null)).Should().Throw <ArgumentNullException>(); Executing.This(() => TeaFile <int> .Append(null, ItemDescriptionElements.None)).Should().Throw <ArgumentNullException>(); var stream = new MemoryStream(); using (var tf = TeaFile <int> .Create(stream)) { tf.Write(Enumerable.Range(100, 7)); } stream.Position = 0; using (var tf = TeaFile <int> .OpenRead(stream)) { tf.Items.GetEnumerator().Should().Not.Be.Null(); } }
public void ZeroTeaFile() { var filename = Path.GetFullPath("TeaFileTest_ZeroTeaFile.tea"); using (var ms = new FileStream(filename, FileMode.Create)) { var w = new BinaryWriter(ms); w.Write(HeaderManager.Signature); // sig w.Write((long)32); // itemstart w.Write((long)0); // itemendmarker w.Write((long)0); // sectioncount } var fi = new FileInfo(filename); fi.Length.Should().Be(32); using (var tf = TeaFile.OpenRead(filename)) { ((IItemReader)tf).CanRead.Should().Be.False(); tf.Name.Should().Be(filename); Executing.This(() => tf.Items.ToString()).Should().Throw <InvalidOperationException>(); Executing.This(() => tf.Read()).Should().Throw <InvalidOperationException>(); Executing.This(() => tf.GetFieldValue(0, null)).Should().Throw <ArgumentNullException>(); Executing.This(() => tf.GetEventTime(null)).Should().Throw <InvalidOperationException>(); tf.Description.Should().Not.Be.Null(); // in summary, a TeaFile that opens a TeaFile without description cannot do much. Being able to open it // gives the information that the file has no description. Moreover, a TeaFile might hold no item description // but for instance a content description which would be readable although no access to the items is available. } }
public void OpenWrite() { var filename = "TeaFileTTest_OpenWrite.tea"; using (var tf = TeaFile <int> .Create(filename)) { tf.Count.Should().Be(0); tf.Write(Enumerable.Range(1, 10)); tf.Count.Should().Be(10); } using (var tf = TeaFile <int> .OpenRead(filename)) { tf.Items.ForEach(Console.WriteLine); } using (var tf = TeaFile <int> .OpenWrite(filename)) { tf.Count.Should().Be(10); tf.Write(Enumerable.Range(1, 5)); tf.Count.Should().Be(10); tf.Write(Enumerable.Range(1, 5)); tf.Count.Should().Be(10); tf.Write(Enumerable.Range(1, 5)); tf.Count.Should().Be(15); } Console.WriteLine(".................."); using (var tf = TeaFile <int> .OpenRead(filename)) { tf.Items.ForEach(Console.WriteLine); } }
public void GetEnumeratorTest() { var filename = "ItemCollectionTest_GetEnumeratorTest.tea"; using (var tf = TeaFile <int> .Create(filename)) { tf.Write(Enumerable.Range(2, 4)); } using (var tf = TeaFile.OpenRead(filename)) { var e = tf.Items.GetEnumerator(0); e.MoveNext().Should().Be.True(); e.Current.Values[0].Should().Be(2); e.MoveNext().Should().Be.True(); e.Current.Values[0].Should().Be(3); e.MoveNext().Should().Be.True(); e.Current.Values[0].Should().Be(4); e.MoveNext().Should().Be.True(); e.Current.Values[0].Should().Be(5); e.MoveNext().Should().Be.False(); e = tf.Items.GetEnumerator(2); e.MoveNext().Should().Be.True(); e.Current.Values[0].Should().Be(4); e.MoveNext().Should().Be.True(); e.Current.Values[0].Should().Be(5); e.MoveNext().Should().Be.False(); } }
public void OpenWriteStream() { Stream stream = new MemoryStream(); using (var tf = TeaFile <int> .Create(stream)) { tf.Write(Enumerable.Range(1, 10)); } stream.Position = 0; using (var tf = TeaFile <int> .OpenWrite(stream)) { tf.Write(Enumerable.Range(70, 5)); } stream.Position = 0; using (var tf = TeaFile <int> .OpenRead(stream)) { tf.Count.Should().Be(10); tf.Read().Should().Be(70); tf.Read().Should().Be(71); tf.Read().Should().Be(72); tf.Read().Should().Be(73); tf.Read().Should().Be(74); tf.Read().Should().Be(6); tf.Read().Should().Be(7); tf.Read().Should().Be(8); tf.Read().Should().Be(9); tf.Read().Should().Be(10); } }
public void CreateZeroTeaFile() { var ms = new MemoryStream(); var tf = TeaFile <Event <OHLCV> > .Create(ms, null, null, false); tf.Dispose(); ms.Length.Should().Be(32); ms.Position = 0; var r = new BinaryReader(ms); var bom = r.ReadInt64(); bom.Should().Be(0x0d0e0a0402080500); var itemstart = r.ReadInt64(); itemstart.Should().Be(32); var eof = r.ReadInt64(); eof.Should().Be(0); var sectionCount = r.ReadInt64(); sectionCount.Should().Be(0); ms.Position = 0; var tf2 = TeaFile.OpenRead(ms); var d = tf2.Description; d.ItemDescription.Should().Be.Null(); d.ContentDescription.Should().Be.Null(); d.NameValues.Should().Be.Null(); }
public void DiscDriveFailureDuringCreate() { var stream = new TestStream(); stream.FailAfterPosition = 17; Executing.This(() => TeaFile <int> .Create(stream)).Should().Throw <IOException>(); }
public void ZeroTeaFilesEvilBrother() { var filename = Path.GetFullPath("TeaFileTest_ZeroTeaFilesEvilBrother.tea"); using (var ms = new FileStream(filename, FileMode.Create)) { var w = new BinaryWriter(ms); w.Write(HeaderManager.Signature); // sig w.Write((long)32); // itemstart w.Write((long)32); // itemendmarker <- zero tea file's evil brother has a marker with 32 w.Write((long)0); // sectioncount } var fi = new FileInfo(filename); fi.Length.Should().Be(32); using (var tf = TeaFile.OpenRead(filename)) { ((IItemReader)tf).CanRead.Should().Be.False(); tf.Name.Should().Be(filename); tf.Description.Should().Not.Be.Null(); Executing.This(() => tf.Items.ToString()).Should().Throw <InvalidOperationException>(); Executing.This(() => tf.Read()).Should().Throw <InvalidOperationException>(); } }
public void FilePositionAfterWritingItems() { var stream = new MemoryStream(); using (var tf = TeaFile <int> .Create(stream)) { tf.ItemAreaSize.Should().Be(0); stream.Position.Should().Be(stream.Length); stream.Position.Should().Be(tf.ItemAreaStart); tf.ItemAreaStart.Should().Be(80); tf.Write(11); tf.ItemAreaStart.Should().Be(80); tf.ItemAreaEnd.Should().Be(84); tf.ItemAreaSize.Should().Be(4); tf.Count.Should().Be(1); stream.Position.Should().Be(84); stream.Position.Should().Be(84); tf.Write(7); tf.ItemAreaStart.Should().Be(80); tf.ItemAreaEnd.Should().Be(88); tf.ItemAreaSize.Should().Be(8); tf.Count.Should().Be(2); stream.Position.Should().Be(88); stream.Position.Should().Be(88); } }
public void TimeValuesAreCorrect() { Time.Scale = Timescale.Net; const string filename = "TeaFileTest_TimeValuesAreCorrect.tea"; using (var tf = TeaFile <OHLCV3> .Create(filename)) { tf.Write(new OHLCV3 { High = 71, Low = 20, Open = 33, Close = 21, Time = new DateTime(2000, 7, 6) }); tf.Write(new OHLCV3 { High = 72, Low = 20, Open = 34, Close = 22, Time = new DateTime(2000, 7, 11) }); } using (var tf = TeaFile.OpenRead(filename)) { tf.Items.Count.Should().Be(2); var timeField = tf.Description.ItemDescription.GetFieldByName("Time"); var item = tf.Read(); var time = tf.GetFieldValue(item, timeField); time.Should().Be(new Time(2000, 7, 6)); item = tf.Read(); time = tf.GetFieldValue(item, timeField); time.Should().Be(new Time(2000, 7, 11)); } }
public void ZeroTeaFilesGoodBrother() { var filename = Path.GetFullPath(MethodBase.GetCurrentMethod() + ".tea"); using (var ms = new FileStream(filename, FileMode.Create)) { var w = new BinaryWriter(ms); w.Write(HeaderManager.Signature); // sig w.Write((long)32); // itemstart w.Write((long)32); // itemendmarker <- zero tea file's evil brother has a marker with 32 w.Write((long)0); // sectioncount 10.Times(() => w.Write(0L)); // increase file length, now the preallocation makes sense, and evil brother becomes a good one } var fi = new FileInfo(filename); fi.Length.Should().Be(32 + 10 * 8); using (var tf = TeaFile.OpenRead(filename)) { ((IItemReader)tf).CanRead.Should().Be.False(); tf.Name.Should().Be(filename); tf.Description.Should().Not.Be.Null(); // the description should never be null Executing.This(() => tf.Items.ToString()).Should().Throw <InvalidOperationException>(); Executing.This(() => tf.Read()).Should().Throw <InvalidOperationException>(); } }
static TeaFile <T> Append(Stream stream, bool ownsStream, Stream headerReadStream, ItemDescriptionElements elementsToValidate = ItemDescriptionElements.All) { var tf = new TeaFile <T>(); try { TeaFileDescription description; tf.core = new TeaFileCore(stream, ownsStream); // A file opened for appending, cannot be read. Therefore we create a second file, read it and assign its description to the current TeaFile<> instance. using (var tfheader = OpenRead(headerReadStream, false, elementsToValidate)) // we pass headerStream ownership to tfheader, so it will be closed after header reaeding. { description = tfheader.Description; if (!tfheader.core.CanAppend) { throw new IOException("Cannot append to file because it has preallocated space between the end of the item area and the end of the file."); } tf.core.Assign(tfheader.ItemAreaStart, tfheader.core.ItemAreaEndMarker); } // if the stream is a filestream that was opened in FileMode.Append, this call is redundant. // this line is here for the allowed case were the stream and headerstream point to the same stream. tf.SetFilePointerToEnd(); tf.core.Description = description; tf.buffer = new SafeBuffer <T>(stream); return(tf); } catch (Exception) { tf.Dispose(); throw; } }
static TeaFile <T> OpenRead(Stream stream, bool ownsStream, ItemDescriptionElements elementsToValidate) { var tf = new TeaFile <T>(); try { tf.core = new TeaFileCore(stream, ownsStream); tf.buffer = new SafeBuffer <T>(stream); tf.core.ReadHeader(); // reflecting the current type incurs some cost, so we do it only if we are asked to consider // current item layout to check it against to layout described in the file ItemDescription accessorDescription = null; if (elementsToValidate != ItemDescriptionElements.None) { accessorDescription = ItemDescription.FromAnalysis <T>(); } tf.core.IsAccessibleWith(accessorDescription, elementsToValidate); return(tf); } catch (Exception) { tf.Dispose(); throw; } }
/// <summary> /// Creates a TeaFile, using the specified stream as the underlying storage media. /// </summary> /// <param name="stream">The stream.</param> /// <param name="ownsStream">If true, the instance returned owns the stream, such that disposing the returned instance also disposes <paramref name="stream"/>.</param> /// <param name="contentDescription">The content description.</param> /// <param name="nameValues">The name values.</param> /// <param name="includeItemDescription">if set to <c>true</c> [include item description].</param> /// <returns></returns> /// <remarks> /// Instead of creating a new <see cref="FileStream"/>, this method takes the <see cref="Stream"/> passed. This provides /// more control over the stream, like setting specific <see cref="FileShare"/> attributes. It also allows usage of /// alternative storage medias like <see cref="MemoryStream"/>. /// </remarks> public static TeaFile <T> Create(Stream stream, bool ownsStream, string contentDescription = null, NameValueCollection nameValues = null, bool includeItemDescription = true) { if (stream == null) { throw new ArgumentNullException("stream"); } var tf = new TeaFile <T>(); try { tf.core = new TeaFileCore(stream, ownsStream); tf.buffer = new SafeBuffer <T>(stream); if (includeItemDescription) { tf.Description.ItemDescription = ItemDescription.FromAnalysis <T>(); } tf.Description.ContentDescription = contentDescription; tf.Description.NameValues = nameValues; tf.Description.Timescale = Time.Scale; // The tf.core.WriteHeader(); tf.Flush(); return(tf); } catch (Exception) { tf.Dispose(); throw; } }
public void ItemsT_Enumerating_Returns_Correct_Values() { using (TeaFile <OHLCV> f = TeaFile <OHLCV> .Create(Guid.NewGuid() + "lab1.tea")) { var firstValue = new OHLCV { Open = 111 }; var someValue = new OHLCV { Open = 222 }; var lastValue = new OHLCV { Open = 333 }; List <OHLCV> values = new List <OHLCV>(); values.Add(firstValue); values.Add(someValue); values.Add(lastValue); int i = 0; foreach (OHLCV ohlcv in f.Items) { Assert.AreEqual(values[i], ohlcv); } } }
public void ItemsT_property_returns_value() { using (TeaFile <OHLCV> f = TeaFile <OHLCV> .Create(Guid.NewGuid() + "lab1.tea")) { var items = f.Items; Assert.IsNotNull(items); } }
public void ItemsT_property_has_count_0() { using (TeaFile <OHLCV> f = TeaFile <OHLCV> .Create(Guid.NewGuid() + "lab1.tea")) { var items = f.Items; Assert.AreEqual(0, items.Count); } }
public void OpeningFileWithWrongSignatureThrowsFileFormatException() { const string filename = "TeaFileTest_OpeningFileWithWrongSignatureThrowsFileFormatException.tea"; File.WriteAllBytes(filename, BitConverter.GetBytes(1700L)); // wrong signature value Executing.This(() => TeaFile.OpenRead(filename)).Should().Throw <FileFormatException>() .Exception.Message.Should().Contain("Signature"); }
public void OpeningEmptyFileThrowsFileFormatException() { const string filename = "TeaFileTest_OpeningEmptyFileThrowsException.tea"; File.WriteAllBytes(filename, new byte[0]); var ex = Executing.This(() => TeaFile.OpenRead(filename)).Should().Throw <FileFormatException>().Exception; Console.WriteLine(ex.Message); }
public void TeaFileDoesNotDisposeExternalStream() { var stream = new TestStream(); using (var tf = TeaFile <int> .Create(stream)) { } stream.WasDisposed.Should().Be.False(); }
public void OpeningFileWithCorrrectSignatureThrowsExceptionWithoutSignatureMessage() { var filename = Path.GetTempFileName(); File.WriteAllBytes(filename, BitConverter.GetBytes(0x0d0e0a0402080500)); var ex = Executing.This(() => TeaFile.OpenRead(filename)).Should().Throw <FileFormatException>().Exception; ex.Message.Should().Not.Contain("Signature"); Console.WriteLine(ex.Message); }
public void IsTimeSeriesTrue() { var stream = new MemoryStream(); using (var tf = TeaFile <Event <int> > .Create(stream)) { var d = tf.Description; d.ItemDescription.HasEventTime.Should().Be.True(); } }
public void AccessorRawMemoryMappingTest() { var filename = "TeaFileTTest_AccessorRawMemoryMappingTest.tea"; using (TeaFile <Tick> .Create(filename)) { // an empty file holding the description is enough for this test } Executing.This(() => TeaFile <OHLCV> .OpenRawMemoryMapping(filename)).Should().Throw <TypeMismatchException>(); }
public void TestStreamTest() { TestStream stream; using (stream = new TestStream()) using (var tf = TeaFile <int> .Create(stream)) { } stream.WasDisposed.Should().Be.True(); }
public void OpenReadOfNonExistentFile() { const string filename = "TeaFileTTest_OpenReadOfNonExistentFile.tea"; Executing.This(() => TeaFile <int> .OpenRead(filename)).Should().Throw(); GC.Collect(); GC.WaitForPendingFinalizers(); GC.Collect(); }
public void ItemsT_Enumerating_No_Enumeration_On_Empty_Collection() { using (TeaFile <OHLCV> f = TeaFile <OHLCV> .Create(Guid.NewGuid() + "lab1.tea")) { foreach (OHLCV ohlcv in f.Items) { Assert.Fail("no values are available, so no iteration should occur"); } } }
public void Flush() { var filename = "TeaFileTTest_Flush.tea"; var tf = TeaFile <int> .Create(filename); tf.Write(Enumerable.Range(1, 10)); tf.Flush(); // we can easily test only that the call does not except tf.Close(); Executing.This(tf.Flush).Should().Throw(); // and that it fails after closing the stream }
public void ItemsT_property_has_count_4() { using (TeaFile <OHLCV> f = TeaFile <OHLCV> .Create(Guid.NewGuid() + "lab1.tea")) { 4.Times(() => f.Write(new OHLCV { Open = 111 })); var items = f.Items; Assert.AreEqual(4, items.Count); } }
public void ExoticCoverage() { Executing.This(() => TeaFile.OpenRead((string)null)).Should().Throw <ArgumentNullException>(); Executing.This(() => TeaFile.OpenRead((Stream)null)).Should().Throw <ArgumentNullException>(); var stream = TestUtils.GetTeaFileEventInt7Values(); var tf = TeaFile.OpenRead(stream); Executing.This(() => tf.GetFieldValue(null, null)).Should().Throw <ArgumentNullException>(); Item item = new Item(2); Executing.This(() => tf.GetFieldValue(item, null)).Should().Throw <ArgumentNullException>(); }
public void TimeScaleIsSetInDescriptionOfCreatedFile() { var filename = "TeaFileTTest_TimeScaleIsSetInDescriptionOfCreatedFile.tea"; File.Delete(filename); using (var tf = TeaFile <Tick> .Create(filename)) { tf.Description.Timescale.HasValue.Should().Be.True(); tf.Description.Timescale.Value.Epoch.Should().Be(Time.Scale.Epoch); tf.Description.Timescale.Value.TicksPerDay.Should().Be(Time.Scale.TicksPerDay); } }
static void WriteDailyTicks(TeaFile<Tick> tf, Time day, bool isGoodDay) { Time t = day.AddHours(9); // start trading session at 09:00 Time end = day.AddHours(17.5); // end trading session at 17:30 while (t < end) { // on a good day, we write many ticks, on a bad day however only 1 percent as much if (isGoodDay || DrawRandom(1)) { double p = r.NextDouble() * 100000.0; tf.Write(new Tick {Time = t, Price = p, Volume = 10}); } t = t.AddSeconds(15 + r.Next(0, 20)); } }
static TeaFile OpenRead(Stream stream, bool ownsStream) { var tf = new TeaFile(); try { tf.core = new TeaFileCore(stream, ownsStream); tf.core.ReadHeader(); // protect against empty Item structs if (tf.Description.ItemDescription != null) { if (!tf.Description.ItemDescription.Fields.Any()) { throw new ItemException("Cannot read this file because the item has no fields according to its item description in the file."); } } tf.reader = new BinaryReader(tf.core.Stream); if (tf.Description.ItemDescription != null) { // A field might occupy equal or more bytes than the size of its type due to padding bytes // inserted between the fields or between items in the ItemArray. The paddingBytes array // holds the number of bytes that will be read after reading a field in order to set the // file pointer to the next field. tf.fieldSpacings = tf.GetFieldSpacings(); } return tf; } catch { tf.Dispose(); // since we will not hand out the disposable TeaFile instance, // we must close the filestream if header reading failed! throw; } }