├── .gitignore
├── Coverage.testsettings
├── Examples
├── AnalyzeTicks
│ ├── AnalyzeTicks.csproj
│ └── Program.cs
├── Benchmarks
│ ├── Benchmarks.csproj
│ ├── ComputerSpecs.cs
│ ├── Operations.cs
│ ├── Program.cs
│ ├── Runner.cs
│ ├── Utils.cs
│ └── results.htm
├── CreateSessions
│ ├── CreateSessions.csproj
│ └── Program.cs
├── CreateTicks
│ ├── CreateTicks.csproj
│ └── Program.cs
├── GetSnapshot
│ ├── GetSnapshot.csproj
│ └── Program.cs
├── ItemTypes
│ ├── ItemTypes.cs
│ └── ItemTypes.csproj
└── Sum
│ ├── Program.cs
│ └── Sum.csproj
├── LICENSE
├── Lib
├── Moq.dll
├── Moq.xml
├── SharpTestsEx.dll
└── SharpTestsEx.xml
├── Normal.testsettings
├── README.md
├── TeaFiles.Net.sln
├── TeaFiles.Test
├── Access
│ ├── ItemCollectionTest.cs
│ ├── ManagedMemoryMappingTest.cs
│ ├── RawMemoryMappingTest.cs
│ └── SafeBufferTest.cs
├── Base
│ ├── EventTest.cs
│ ├── NameValueTest.cs
│ ├── TimeScaleTest.cs
│ └── TimeTest.cs
├── Description
│ ├── DescriptionTest.cs
│ ├── FieldTest.cs
│ ├── ItemDescriptionDetailsTest.cs
│ ├── ItemDescriptionTest.cs
│ └── TeaTypeTest.cs
├── ExtensionsTest.cs
├── Header
│ ├── HeaderManagerTest.cs
│ └── Sections
│ │ ├── ContentSectionFormatterTest.cs
│ │ ├── ItemSectionFormatterTest.cs
│ │ ├── NameValueSectionFormatterTest.cs
│ │ └── TimeSectionFormatterTest.cs
├── IO
│ ├── FileIOTest.cs
│ ├── FormattedReaderTest.cs
│ └── FormattedWriterTest.cs
├── ItemsTTest.cs
├── Layout
│ ├── ByteSearcherTest.cs
│ └── LayoutAnalyzerTest.cs
├── Properties
│ └── AssemblyInfo.cs
├── SampleItems
│ └── ItemTypes.cs
├── SnapshotTest.cs
├── TeaFileCoreTest.cs
├── TeaFileTTest.cs
├── TeaFileTest.cs
├── TeaFiles.Test.csproj
├── TestStream.cs
├── TestUtils.cs
└── packages.config
├── TeaFiles
├── Access
│ ├── Extensions.cs
│ ├── ManagedMemoryMapping.cs
│ ├── RawMemoryMapping.cs
│ ├── Typed
│ │ ├── ItemsCollectionT.cs
│ │ └── SafeBufferT.cs
│ └── UnTyped
│ │ ├── IItemReader.cs
│ │ ├── Item.cs
│ │ └── ItemCollection.cs
├── Base
│ ├── Event.cs
│ ├── NameValue.cs
│ ├── Time.cs
│ └── TimeScale.cs
├── Description
│ ├── DescriptionSource.cs
│ ├── Field.cs
│ ├── FieldType.cs
│ ├── ItemDescription.cs
│ ├── ItemDescriptionElements.cs
│ ├── TeaFileDescription.cs
│ └── TimeFormat.cs
├── Exceptions.cs
├── Extensions.cs
├── GlobalSuppressions.cs
├── Header
│ ├── HeaderManager.cs
│ ├── ISectionFormatter.cs
│ ├── ReadContext.cs
│ ├── Sections
│ │ ├── ContentSectionFormatter.cs
│ │ ├── ItemSectionFormatter.cs
│ │ ├── NameValueSectionFormatter.cs
│ │ └── TimeSectionFormatter.cs
│ └── WriteContext.cs
├── IO
│ ├── FileIO.cs
│ ├── FormattedReader.cs
│ ├── FormattedWriter.cs
│ └── Interfaces.cs
├── Layout
│ ├── AnalyzedField.cs
│ ├── ByteSearcher.cs
│ ├── FieldPath.cs
│ └── LayoutAnalyzer.cs
├── License.txt
├── TeaFile.cs
├── TeaFileCore.cs
├── TeaFileT.cs
├── TeaFiles.csproj
├── TeaFiles.ruleset
└── TeaTime.cs
├── Usage
├── Program.cs
└── Usage.csproj
├── azure-pipelines.yml
└── normal32.testsettings
/.gitignore:
--------------------------------------------------------------------------------
1 | # Build Folders (you can keep bin if you'd like, to store dlls and pdbs)
2 | [Bb]in/
3 | [Oo]bj/
4 |
5 | # mstest test results
6 | TestResults
7 |
8 | ## Ignore Visual Studio temporary files, build results, and
9 | ## files generated by popular Visual Studio add-ons.
10 |
11 | # User-specific files
12 | *.suo
13 | *.user
14 | *.sln.docstates
15 |
16 | # Build results
17 | [Dd]ebug/
18 | [Rr]elease/
19 | x64/
20 | *_i.c
21 | *_p.c
22 | *.ilk
23 | *.meta
24 | *.obj
25 | *.pch
26 | *.pdb
27 | *.pgc
28 | *.pgd
29 | *.rsp
30 | *.sbr
31 | *.tlb
32 | *.tli
33 | *.tlh
34 | *.tmp
35 | *.log
36 | *.vspscc
37 | *.vssscc
38 | .builds
39 |
40 | # Visual C++ cache files
41 | ipch/
42 | *.aps
43 | *.ncb
44 | *.opensdf
45 | *.sdf
46 |
47 | # Visual Studio profiler
48 | *.psess
49 | *.vsp
50 | *.vspx
51 |
52 | # Guidance Automation Toolkit
53 | *.gpState
54 |
55 | # ReSharper is a .NET coding add-in
56 | _ReSharper*
57 |
58 | # NCrunch
59 | *.ncrunch*
60 | .*crunch*.local.xml
61 |
62 | # Installshield output folder
63 | [Ee]xpress
64 |
65 | # DocProject is a documentation generator add-in
66 | DocProject/buildhelp/
67 | DocProject/Help/*.HxT
68 | DocProject/Help/*.HxC
69 | DocProject/Help/*.hhc
70 | DocProject/Help/*.hhk
71 | DocProject/Help/*.hhp
72 | DocProject/Help/Html2
73 | DocProject/Help/html
74 |
75 | # Click-Once directory
76 | publish
77 |
78 | # Publish Web Output
79 | *.Publish.xml
80 |
81 | # NuGet Packages Directory
82 | packages
83 |
84 | # Windows Azure Build Output
85 | csx
86 | *.build.csdef
87 |
88 | # Windows Store app package directory
89 | AppPackages/
90 |
91 | # Others
92 | [Bb]in
93 | [Oo]bj
94 | sql
95 | TestResults
96 | [Tt]est[Rr]esult*
97 | *.Cache
98 | ClientBin
99 | [Ss]tyle[Cc]op.*
100 | ~$*
101 | *.dbmdl
102 | Generated_Code #added for RIA/Silverlight projects
103 |
104 | # Backup & report files from converting an old project file to a newer
105 | # Visual Studio version. Backup files are not needed, because we have git ;-)
106 | _UpgradeReport_Files/
107 | Backup*/
108 | UpgradeLog*.XML
109 | /.vs/*
110 |
--------------------------------------------------------------------------------
/Coverage.testsettings:
--------------------------------------------------------------------------------
1 |
2 |
3 | Run tests and test code coverage.
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
--------------------------------------------------------------------------------
/Examples/AnalyzeTicks/AnalyzeTicks.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Debug
5 | x86
6 | 8.0.30703
7 | 2.0
8 | {35B0A885-3123-43B7-8DCA-B4CAD7B5AD41}
9 | Exe
10 | Properties
11 | ACME.Examples
12 | AnalyzeTicks
13 | v4.7.2
14 |
15 |
16 | 512
17 |
18 |
19 | true
20 | ..\..\Bin\
21 | DEBUG;TRACE
22 | full
23 | AnyCPU
24 | ..\..\Bin\AnalyzeTicks.exe.CodeAnalysisLog.xml
25 | true
26 | GlobalSuppressions.cs
27 | prompt
28 | MinimumRecommendedRules.ruleset
29 | ;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets
30 | true
31 | ;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules
32 | true
33 | true
34 | false
35 |
36 |
37 | ..\..\Bin\
38 | TRACE
39 | true
40 | pdbonly
41 | AnyCPU
42 | ..\..\Bin\AnalyzeTicks.exe.CodeAnalysisLog.xml
43 | true
44 | GlobalSuppressions.cs
45 | prompt
46 | MinimumRecommendedRules.ruleset
47 | ;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets
48 | ;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules
49 | true
50 | true
51 | false
52 | false
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 | {1CADE377-2821-480D-A0E7-34F224886AF6}
69 | TeaFiles
70 |
71 |
72 | {DD952649-AD45-4B89-B87E-28F0B876171E}
73 | ItemTypes
74 |
75 |
76 |
77 |
78 |
79 |
80 |
87 |
--------------------------------------------------------------------------------
/Examples/AnalyzeTicks/Program.cs:
--------------------------------------------------------------------------------
1 | // copyright discretelogics 2012. released under the gpl v3. see license.txt for details.
2 | using System;
3 | using System.Collections.Generic;
4 | using System.Diagnostics;
5 | using System.Linq;
6 | using TeaTime;
7 |
8 | namespace ACME.Examples
9 | {
10 | class Program
11 | {
12 | class TradingSession
13 | {
14 | public Time Begin;
15 | public Time End;
16 | public int TickCount;
17 |
18 | public TradingSession(Time time)
19 | {
20 | this.Begin = time.Date;
21 | this.End = this.Begin.AddDays(1);
22 | }
23 |
24 | public override string ToString()
25 | {
26 | return this.Begin + " " + this.TickCount;
27 | }
28 | }
29 |
30 | static void Main(string[] args)
31 | {
32 | try
33 | {
34 | if (args.Count() < 1) throw new Exception("Usage: AnalyzeTicks [m]emorymapped|read [n]times");
35 | string filename = args[0];
36 | bool memoryMapped = args.Count() >= 2
37 | ? args[1].StartsWith("m", StringComparison.InvariantCultureIgnoreCase)
38 | : false;
39 | int n = args.Count() >= 3 ? int.Parse(args[2]) : 1;
40 |
41 | Console.WriteLine(Environment.Is64BitProcess ? "64bit" : "32bit");
42 |
43 | for (int i = 1; i <= n; i++)
44 | {
45 | Console.WriteLine("----------------------------------");
46 | Console.WriteLine(i + ". run");
47 | var sw = Stopwatch.StartNew();
48 | Run(filename, memoryMapped, n == 1);
49 | sw.Stop();
50 | Console.WriteLine("execution time = " + sw.Elapsed.TotalMilliseconds + "ms");
51 | }
52 | }
53 | catch (Exception ex)
54 | {
55 | Console.WriteLine(ex.Message);
56 | }
57 | }
58 |
59 | class Statistics
60 | {
61 | public double MinPrice;
62 | public double MaxPrice;
63 | public List Sessions;
64 |
65 | public Statistics()
66 | {
67 | this.Sessions = new List();
68 | }
69 | }
70 |
71 | static void Run(string filename, bool memoryMapped, bool displayValues)
72 | {
73 | using (var tf = TeaFile.OpenRead(filename, ItemDescriptionElements.None))
74 | {
75 | if (tf.Items.Count == 0) throw new Exception("File holds no items.");
76 | }
77 |
78 | Statistics stats;
79 | if (memoryMapped)
80 | {
81 | stats = GetSessionDataMemMapped(filename);
82 | }
83 | else
84 | {
85 | stats = GetSessionData(filename);
86 | }
87 |
88 | int minTransactions = int.MaxValue;
89 | int maxTransactions = int.MinValue;
90 | foreach (var session in stats.Sessions)
91 | {
92 | minTransactions = Math.Min(minTransactions, session.TickCount);
93 | maxTransactions = Math.Max(maxTransactions, session.TickCount);
94 | }
95 | Console.WriteLine("min price = " + stats.MinPrice);
96 | Console.WriteLine("max price = " + stats.MaxPrice);
97 | Console.WriteLine("min ticks per session = " + minTransactions);
98 | Console.WriteLine("max ticks per session = " + maxTransactions);
99 |
100 | var tickCounts = stats.Sessions.Select(s => s.TickCount).ToArray();
101 | Array.Sort(tickCounts);
102 | int median = tickCounts[tickCounts.Length / 2];
103 | Console.WriteLine("median = " + median);
104 |
105 | if (displayValues)
106 | {
107 | double minimumExpectedTicksPerSession = median / 2.0;
108 | Console.WriteLine("First 10 sessions:");
109 | foreach (var s in stats.Sessions.Take(10))
110 | {
111 | Console.WriteLine(s + " " + ((s.TickCount >= minimumExpectedTicksPerSession) ? "OK" : "QUESTIONABLE"));
112 | }
113 | }
114 | }
115 |
116 | static Statistics GetSessionDataMemMapped(string filename)
117 | {
118 | using (var mf = RawMemoryMapping.OpenRead(filename))
119 | unsafe
120 | {
121 | var stats = new Statistics();
122 | Tick* firstTick = (Tick*)mf.ItemAreaStart;
123 | double minPrice = firstTick->Price;
124 | double maxPrice = firstTick->Price;
125 | var session = new TradingSession(firstTick->Time);
126 | stats.Sessions.Add(session);
127 | for (var t = firstTick; t != mf.ItemAreaEnd; t++)
128 | {
129 | if (t->Time >= session.End)
130 | {
131 | session = new TradingSession(t->Time);
132 | stats.Sessions.Add(session);
133 | }
134 | session.TickCount++;
135 | minPrice = Math.Min(t->Price, minPrice);
136 | maxPrice = Math.Max(t->Price, maxPrice);
137 | }
138 | stats.MinPrice = minPrice;
139 | stats.MaxPrice = maxPrice;
140 | return stats;
141 | }
142 | }
143 |
144 | static Statistics GetSessionData(string filename)
145 | {
146 | using (var tf = TeaFile.OpenRead(filename, ItemDescriptionElements.None))
147 | {
148 | var stats = new Statistics();
149 | Tick firstTick = tf.Items.First();
150 | double minPrice = firstTick.Price;
151 | double maxPrice = firstTick.Price;
152 | var session = new TradingSession(firstTick.Time);
153 | stats.Sessions.Add(session);
154 | int n = 0;
155 | foreach (var tick in tf.Items)
156 | {
157 | if (tick.Time >= session.End)
158 | {
159 | session = new TradingSession(tick.Time);
160 | stats.Sessions.Add(session);
161 | }
162 | session.TickCount++;
163 |
164 | minPrice = Math.Min(tick.Price, minPrice);
165 | maxPrice = Math.Max(tick.Price, maxPrice);
166 | n++;
167 | }
168 | stats.MinPrice = minPrice;
169 | stats.MaxPrice = maxPrice;
170 | return stats;
171 | }
172 | }
173 | }
174 | }
175 |
--------------------------------------------------------------------------------
/Examples/Benchmarks/Benchmarks.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Debug
5 | x86
6 | 8.0.30703
7 | 2.0
8 | {E1A16FF5-631B-4CC9-848F-61FF1EA3B961}
9 | Exe
10 | Properties
11 | TeaTime.Benchmarks
12 | Benchmarks
13 | v4.7.2
14 |
15 |
16 | 512
17 |
18 |
19 | x86
20 | true
21 | full
22 | false
23 | bin\Debug\
24 | DEBUG;TRACE
25 | prompt
26 | 4
27 | false
28 |
29 |
30 | x86
31 | pdbonly
32 | true
33 | bin\Release\
34 | TRACE
35 | prompt
36 | 4
37 | false
38 |
39 |
40 | true
41 | ..\..\Bin\
42 | DEBUG;TRACE
43 | full
44 | AnyCPU
45 | bin\Debug\DiscreteLogics.TeaFile.Benchmarks.exe.CodeAnalysisLog.xml
46 | true
47 | GlobalSuppressions.cs
48 | prompt
49 | MinimumRecommendedRules.ruleset
50 | ;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets
51 | true
52 | ;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules
53 | true
54 | false
55 | true
56 | false
57 |
58 |
59 | ..\..\Bin\
60 | TRACE
61 | true
62 | pdbonly
63 | AnyCPU
64 | bin\Release\DiscreteLogics.TeaFile.Benchmarks.exe.CodeAnalysisLog.xml
65 | true
66 | GlobalSuppressions.cs
67 | prompt
68 | MinimumRecommendedRules.ruleset
69 | ;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets
70 | true
71 | ;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules
72 | true
73 | true
74 | false
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 | PreserveNewest
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 | {1CADE377-2821-480D-A0E7-34F224886AF6}
105 | TeaFiles
106 |
107 |
108 | {DD952649-AD45-4B89-B87E-28F0B876171E}
109 | ItemTypes
110 |
111 |
112 |
113 |
120 |
--------------------------------------------------------------------------------
/Examples/Benchmarks/ComputerSpecs.cs:
--------------------------------------------------------------------------------
1 | // code adopted from MeasureIt by Vance Morrison - http://blogs.msdn.com/b/vancem/archive/2009/02/06/measureit-update-tool-for-doing-microbenchmarks.aspx
2 | using System.Management;
3 |
4 | namespace TeaTime.Benchmarks
5 | {
6 | public class ComputerSpecs
7 | {
8 | public string Name;
9 | public string Manufacturer;
10 | public string Model;
11 |
12 | public string OperatingSystem;
13 | public string OperatingSystemVersion;
14 | public int OperatingSystemServicePack;
15 |
16 | public int NumberOfDisks;
17 | public string SystemDiskModel;
18 |
19 | public int NumberOfProcessors;
20 | public string ProcessorName;
21 | public string ProcessorDescription;
22 | public int ProcessorClockSpeedMhz;
23 |
24 | public int MemoryMBytes;
25 | public int L1KBytes;
26 | public int L2KBytes;
27 |
28 | public ComputerSpecs()
29 | {
30 | ManagementObjectSearcher searcher = new ManagementObjectSearcher("Select * from Win32_ComputerSystem");
31 | foreach (ManagementObject mo in searcher.Get())
32 | {
33 | Name = (string)mo["Caption"];
34 | Manufacturer = (string)mo["Manufacturer"];
35 | Model = (string)mo["Model"];
36 | MemoryMBytes = (int)(((ulong)mo["TotalPhysicalMemory"]) / (1024 * 1024));
37 | }
38 |
39 | searcher = new ManagementObjectSearcher("Select * from Win32_OperatingSystem");
40 | foreach (ManagementObject mo in searcher.Get())
41 | {
42 | OperatingSystem = (string)mo["Caption"];
43 | OperatingSystemVersion = (string)mo["Version"];
44 | OperatingSystemServicePack = (int)(ushort)mo["ServicePackMajorVersion"];
45 | break;
46 | }
47 |
48 | searcher = new ManagementObjectSearcher("Select * from Win32_DiskDrive");
49 | ManagementObjectCollection disks = searcher.Get();
50 | NumberOfDisks = disks.Count;
51 | foreach (ManagementObject mo in disks)
52 | {
53 | SystemDiskModel = (string)mo["Caption"];
54 | break;
55 | }
56 |
57 | searcher = new ManagementObjectSearcher("Select * from Win32_Processor");
58 | ManagementObjectCollection processors = searcher.Get();
59 | NumberOfProcessors = processors.Count;
60 | foreach (ManagementObject mo in processors)
61 | {
62 | ProcessorName = (string)mo["Name"];
63 | ProcessorDescription = (string)mo["Description"];
64 | ProcessorClockSpeedMhz = (int)(uint)mo["MaxClockSpeed"];
65 | // Console.WriteLine(" NumberOfCores: " + mo["NumberOfCores"]);
66 | // Console.WriteLine(" NumberOfLogicalProcessors: " + mo["NumberOfLogicalProcessors"]);
67 | // Console.WriteLine(" L2CacheSize: " + mo["L2CacheSize"]);
68 | break;
69 | }
70 |
71 | searcher = new ManagementObjectSearcher("Select * from Win32_CacheMemory");
72 | foreach (ManagementObject mo in searcher.Get())
73 | {
74 | //Console.WriteLine(" Purpose: " + mo["Purpose"]);
75 | // Console.WriteLine(" InstalledSize: " + mo["InstalledSize"] + " K");
76 | int level = (ushort)mo["Level"] - 2;
77 | // Console.WriteLine(" Level: " + level + " K");
78 | if (level == 1)
79 | L1KBytes += (int)(uint)mo["InstalledSize"];
80 | else if (level == 2)
81 | L2KBytes += (int)(uint)mo["InstalledSize"];
82 | }
83 | }
84 | }
85 | }
86 |
--------------------------------------------------------------------------------
/Examples/Benchmarks/Program.cs:
--------------------------------------------------------------------------------
1 | // copyright discretelogics © 2011
2 | using System;
3 | using System.Collections.Generic;
4 | using System.Diagnostics;
5 | using System.Linq;
6 | using System.IO;
7 | using System.Management;
8 | using System.Reflection;
9 |
10 | namespace TeaTime.Benchmarks
11 | {
12 | class Program
13 | {
14 | static void Main()
15 | {
16 | const long N = 5 * 1000 * 1000;
17 | const string filename = "teafiles.benchmark.htm";
18 |
19 | // compute the sum by formula and print it, as a check value
20 | const long target = (N * (N - 1) / 2);
21 |
22 | Runner runner = new Runner(N);
23 | runner.TargetValue = target;
24 | for (int i = 0; i < 5; i++)
25 | {
26 | Operations.RunAll(runner);
27 | }
28 |
29 | File.Delete(filename);
30 | File.WriteAllText(filename, runner.GetReport());
31 | Process.Start(filename);
32 | }
33 | }
34 | }
--------------------------------------------------------------------------------
/Examples/Benchmarks/Runner.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Diagnostics;
4 | using System.IO;
5 | using System.Linq;
6 | using System.Reflection;
7 | using System.Text;
8 |
9 | namespace TeaTime.Benchmarks
10 | {
11 | class Run
12 | {
13 | public long N;
14 | public TimeSpan ExecutionTime;
15 |
16 | public double OperationsPerSecond
17 | {
18 | get { return N / ExecutionTime.TotalSeconds; }
19 | }
20 | }
21 |
22 | class RunSet
23 | {
24 | public List Runs { get; internal set; }
25 | public double RelativeExecutionTimePercent { get; set; }
26 |
27 | public RunSet()
28 | {
29 | this.Runs = new List();
30 | }
31 |
32 | public double AverageSeconds()
33 | {
34 | return this.Runs.Select(r => r.ExecutionTime.TotalSeconds).Average();
35 | }
36 |
37 | public double AverageOperationsPerSeconds(long n)
38 | {
39 | return (double)n / this.AverageSeconds();
40 | }
41 | }
42 |
43 | class Runner
44 | {
45 | Dictionary operationruns;
46 | public long N;
47 | public long TargetValue;
48 |
49 | public Runner(long N)
50 | {
51 | this.operationruns = new Dictionary();
52 | this.N = N;
53 | }
54 |
55 | public void Measure(string name, Action action)
56 | {
57 | RunSet runs;
58 | if (!this.operationruns.TryGetValue(name, out runs))
59 | {
60 | this.operationruns[name] = runs = new RunSet();
61 | }
62 |
63 | var sw = Stopwatch.StartNew();
64 | action();
65 | sw.Stop();
66 |
67 | var r = new Run();
68 | r.N = this.N;
69 | r.ExecutionTime = sw.Elapsed;
70 | runs.Runs.Add(r);
71 | }
72 |
73 | public void ComputeStats()
74 | {
75 | double maxavgseconds = this.operationruns.Select(runs => runs.Value.AverageSeconds()).Max();
76 | foreach (var runs in operationruns)
77 | {
78 | var percent = runs.Value.AverageSeconds() / maxavgseconds * 100;
79 | percent = Math.Round(percent);
80 | runs.Value.RelativeExecutionTimePercent = percent;
81 | }
82 | }
83 |
84 | public string GetReport()
85 | {
86 | ComputeStats();
87 | var w = new StringWriter();
88 | using (w.Tag("table"))
89 | {
90 | w.WriteLine("benchmark | runs | relative | ops / second |
".Formatted(operationruns.First().Value.Runs.Count));
91 | foreach (var run in this.operationruns)
92 | {
93 | w.WriteLine("{0} | {1}{2} | {3} |
".Formatted(
94 | run.Key,
95 | run.Value.Runs.Select(r => "{0} | ".Formatted(r.ExecutionTime.TotalMilliseconds.ToString("0.00"))).Joined(),
96 | "
".Formatted(run.Value.RelativeExecutionTimePercent),
97 | run.Value.AverageOperationsPerSeconds(this.N).ToString("#,##0")
98 | ));
99 | }
100 | }
101 | w.WriteLine();
102 | using (w.Tag("table"))
103 | {
104 | w.TableRow("computer specs");
105 | var spec = new ComputerSpecs();
106 | foreach (FieldInfo field in spec.GetType().GetFields())
107 | {
108 | w.TableRow(field.Name, field.GetValue(spec) as string);
109 | }
110 | }
111 | string html = File.ReadAllText("results.htm");
112 | html = html.Replace("results", w.ToString());
113 | return html;
114 | }
115 | }
116 | }
117 |
--------------------------------------------------------------------------------
/Examples/Benchmarks/Utils.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.IO;
4 |
5 | namespace TeaTime.Benchmarks
6 | {
7 | static class Extensions
8 | {
9 | public static string Formatted(this string s, params object[] values)
10 | {
11 | return string.Format(s, values);
12 | }
13 |
14 | public static string Joined(this IEnumerable values, string separator = "")
15 | {
16 | return string.Join(separator, values);
17 | }
18 |
19 | public static IDisposable Tag(this TextWriter writer, string tag)
20 | {
21 | writer.Write("<" + tag + ">");
22 | return new Disposable(() => writer.Write("" + tag + ">"));
23 | }
24 |
25 | public static TextWriter TableRow(this TextWriter writer, params string[] tabledata)
26 | {
27 | using (writer.Tag("tr"))
28 | {
29 | foreach (var s in tabledata)
30 | {
31 | using (writer.Tag("td"))
32 | {
33 | writer.Write(s);
34 | }
35 | }
36 | }
37 | writer.WriteLine();
38 | return writer;
39 | }
40 | }
41 |
42 | class Disposable : IDisposable
43 | {
44 | Action action;
45 |
46 | public Disposable(Action a)
47 | {
48 | this.action = a;
49 | }
50 |
51 | public void Dispose()
52 | {
53 | this.action();
54 | }
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/Examples/Benchmarks/results.htm:
--------------------------------------------------------------------------------
1 |
TeaFile API - benchmark
28 |
29 | results
30 |
31 |
--------------------------------------------------------------------------------
/Examples/CreateSessions/CreateSessions.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Debug
5 | x86
6 | 8.0.30703
7 | 2.0
8 | {8CE80E28-D365-46EE-805C-E54550793867}
9 | Exe
10 | Properties
11 | ACME.Examples
12 | CreateSessions
13 | v4.7.2
14 |
15 |
16 | 512
17 |
18 |
19 | true
20 | ..\..\Bin\
21 | DEBUG;TRACE
22 | full
23 | AnyCPU
24 | ..\..\Bin\CreateTicks.exe.CodeAnalysisLog.xml
25 | true
26 | GlobalSuppressions.cs
27 | prompt
28 | MinimumRecommendedRules.ruleset
29 | ;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets
30 | ;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules
31 | false
32 | false
33 | false
34 | false
35 |
36 |
37 | ..\..\Bin\
38 | TRACE
39 | true
40 | pdbonly
41 | AnyCPU
42 | ..\..\Bin\CreateTicks.exe.CodeAnalysisLog.xml
43 | true
44 | GlobalSuppressions.cs
45 | prompt
46 | MinimumRecommendedRules.ruleset
47 | ;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets
48 | false
49 | ;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules
50 | false
51 | false
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 | {1CADE377-2821-480D-A0E7-34F224886AF6}
68 | TeaFiles
69 |
70 |
71 | {DD952649-AD45-4B89-B87E-28F0B876171E}
72 | ItemTypes
73 |
74 |
75 |
76 |
77 |
78 |
79 |
86 |
--------------------------------------------------------------------------------
/Examples/CreateSessions/Program.cs:
--------------------------------------------------------------------------------
1 | // copyright discretelogics 2012. released under the gpl v3. see license.txt for details.
2 | using System;
3 | using System.IO;
4 | using TeaTime;
5 |
6 | namespace ACME.Examples
7 | {
8 | class Program
9 | {
10 | static Random r;
11 |
12 | static bool DrawRandom(double percentageProbability)
13 | {
14 | return r.Next(0, 99) < percentageProbability;
15 | }
16 |
17 | ///
18 | /// This program creates a TeaFile that holds ticks on n days. 90% of the days will be good days, holding around 1000 ticks,
19 | /// while the other 10% are bad days that hold only 1% of that number, so about 10 ticks.
20 | /// Such sample file can then be used to run the AnalyzeTicks program that detects errors in data files.
21 | ///
22 | static void Main(string[] args)
23 | {
24 | try
25 | {
26 | if (args.Length != 2) throw new Exception("Usage: CreateSessions ");
27 | string filename = args[0];
28 | int n = int.Parse(args[1]);
29 | CreateSampleFile(filename, n);
30 | }
31 | catch (Exception ex)
32 | {
33 | Console.WriteLine(ex.Message);
34 | }
35 | }
36 |
37 | static void CreateSampleFile(string filename, int n)
38 | {
39 | r = new Random(1);
40 | var t = new Time(2000, 1, 1);
41 | File.Delete(filename);
42 | using (var tf = TeaFile.Create(filename))
43 | {
44 | while (n-- > 0)
45 | {
46 | bool isGoodDay = DrawRandom(90);
47 | WriteDailyTicks(tf, t, isGoodDay);
48 | t = t.AddDays(1);
49 | }
50 | }
51 | }
52 |
53 | static void WriteDailyTicks(TeaFile tf, Time day, bool isGoodDay)
54 | {
55 | Time t = day.AddHours(9); // start trading session at 09:00
56 | Time end = day.AddHours(17.5); // end trading session at 17:30
57 | while (t < end)
58 | {
59 | // on a good day, we write many ticks, on a bad day however only 1 percent as much
60 | if (isGoodDay || DrawRandom(1))
61 | {
62 | double p = r.NextDouble() * 100000.0;
63 | tf.Write(new Tick {Time = t, Price = p, Volume = 10});
64 | }
65 | t = t.AddSeconds(15 + r.Next(0, 20));
66 | }
67 | }
68 | }
69 | }
70 |
--------------------------------------------------------------------------------
/Examples/CreateTicks/CreateTicks.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Debug
5 | x86
6 | 8.0.30703
7 | 2.0
8 | {1953EC93-0DD1-4433-A00F-7A146DA8793E}
9 | Exe
10 | Properties
11 | ACME.Examples
12 | CreateTicks
13 | v4.7.2
14 |
15 |
16 | 512
17 |
18 |
19 | true
20 | ..\..\Bin\
21 | DEBUG;TRACE
22 | full
23 | AnyCPU
24 | bin\Debug\CreateRandomSeries.exe.CodeAnalysisLog.xml
25 | true
26 | GlobalSuppressions.cs
27 | prompt
28 | MinimumRecommendedRules.ruleset
29 | ;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets
30 | true
31 | ;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules
32 | true
33 | false
34 |
35 |
36 | ..\..\Bin\
37 | TRACE
38 | true
39 | pdbonly
40 | AnyCPU
41 | bin\Release\CreateRandomSeries.exe.CodeAnalysisLog.xml
42 | true
43 | GlobalSuppressions.cs
44 | prompt
45 | MinimumRecommendedRules.ruleset
46 | ;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets
47 | ;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules
48 | false
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 | {1CADE377-2821-480D-A0E7-34F224886AF6}
65 | TeaFiles
66 |
67 |
68 | {DD952649-AD45-4B89-B87E-28F0B876171E}
69 | ItemTypes
70 |
71 |
72 |
73 |
74 |
75 |
76 |
83 |
--------------------------------------------------------------------------------
/Examples/CreateTicks/Program.cs:
--------------------------------------------------------------------------------
1 | // copyright discretelogics 2012. released under the gpl v3. see license.txt for details.
2 | using System;
3 | using System.Diagnostics;
4 | using System.Linq;
5 | using TeaTime;
6 |
7 | namespace ACME.Examples
8 | {
9 | class Program
10 | {
11 | static void Main(string[] args)
12 | {
13 | try
14 | {
15 | if (args.Count() != 2)
16 | {
17 | Console.WriteLine("Usage: CreateTicks ");
18 | return;
19 | }
20 | string filename = args[0];
21 | int n = int.Parse(args[1]);
22 |
23 | var sw = Stopwatch.StartNew();
24 |
25 | Time t = DateTime.Now;
26 | using (var tf = TeaFile.Create(filename))
27 | {
28 | tf.Write(Enumerable.Range(1, n).Select(i => new Tick {Time = t.AddDays(i), Price = i * 101.0, Volume = i * 1000}));
29 | }
30 |
31 | sw.Stop();
32 | Console.WriteLine("execution time = " + sw.Elapsed.TotalMilliseconds + "ms");
33 | }
34 | catch (Exception ex)
35 | {
36 | Console.WriteLine(ex.Message);
37 | }
38 | }
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/Examples/GetSnapshot/GetSnapshot.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Debug
5 | x86
6 | 8.0.30703
7 | 2.0
8 | {AFE98971-4858-4F1F-9E38-435EC3E6D225}
9 | Exe
10 | Properties
11 | ACME.Examples
12 | GetSnapshot
13 | v4.7.2
14 |
15 |
16 | 512
17 |
18 |
19 | true
20 | ..\..\Bin\
21 | DEBUG;TRACE
22 | full
23 | AnyCPU
24 | ..\..\Bin\GetSnapshot.exe.CodeAnalysisLog.xml
25 | true
26 | GlobalSuppressions.cs
27 | prompt
28 | MinimumRecommendedRules.ruleset
29 | ;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets
30 | true
31 | ;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules
32 | false
33 |
34 |
35 | ..\..\Bin\
36 | TRACE
37 | true
38 | pdbonly
39 | AnyCPU
40 | ..\..\Bin\GetSnapshot.exe.CodeAnalysisLog.xml
41 | true
42 | GlobalSuppressions.cs
43 | prompt
44 | MinimumRecommendedRules.ruleset
45 | ;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets
46 | true
47 | ;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules
48 | true
49 | false
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 | {1CADE377-2821-480D-A0E7-34F224886AF6}
66 | TeaFiles
67 |
68 |
69 | {DD952649-AD45-4B89-B87E-28F0B876171E}
70 | ItemTypes
71 |
72 |
73 |
74 |
75 |
76 |
77 |
84 |
--------------------------------------------------------------------------------
/Examples/GetSnapshot/Program.cs:
--------------------------------------------------------------------------------
1 | // copyright discretelogics 2012. released under the gpl v3. see license.txt for details.
2 | using System;
3 | using System.Linq;
4 | using TeaTime;
5 |
6 | namespace ACME.Examples
7 | {
8 | class Program
9 | {
10 | static void Main(string[] args)
11 | {
12 | try
13 | {
14 | if (args.Count() != 1) throw new Exception("Usage: CreateTicks ");
15 | string filename = args.First();
16 |
17 | using (var tf = TeaFile.OpenRead(filename))
18 | {
19 | Console.WriteLine(tf.Description);
20 | Console.WriteLine("ItemAreaStart={0}", tf.ItemAreaStart);
21 | Console.WriteLine("ItemAreaEnd={0}", tf.ItemAreaEnd);
22 | Console.WriteLine("ItemAreaSize={0}", tf.ItemAreaSize);
23 | foreach (Tick tick in tf.Items.Take(5))
24 | {
25 | Console.WriteLine(tick);
26 | }
27 | }
28 | }
29 | catch (Exception ex)
30 | {
31 | Console.WriteLine(ex.Message);
32 | }
33 | }
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/Examples/ItemTypes/ItemTypes.cs:
--------------------------------------------------------------------------------
1 | // copyright discretelogics 2012. released under the gpl v3. see license.txt for details.
2 | using TeaTime;
3 |
4 | namespace ACME.Examples
5 | {
6 | public struct Tick
7 | {
8 | [EventTime]
9 | public Time Time;
10 |
11 | public double Price;
12 | public int Volume;
13 |
14 | public override string ToString()
15 | {
16 | return "Time=" + this.Time + " Price=" + this.Price + " Volume=" + this.Volume;
17 | }
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/Examples/ItemTypes/ItemTypes.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Debug
5 | AnyCPU
6 | 8.0.30703
7 | 2.0
8 | {DD952649-AD45-4B89-B87E-28F0B876171E}
9 | Library
10 | Properties
11 | ACME.Examples
12 | ItemTypes
13 | v4.7.2
14 | 512
15 |
16 |
17 |
18 | true
19 | full
20 | false
21 | ..\..\Bin\
22 | DEBUG;TRACE
23 | prompt
24 | 4
25 | false
26 |
27 |
28 | pdbonly
29 | true
30 | ..\..\Bin\
31 | TRACE
32 | prompt
33 | 4
34 | false
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 | {1CADE377-2821-480D-A0E7-34F224886AF6}
51 | TeaFiles
52 |
53 |
54 |
55 |
56 |
57 |
58 |
65 |
--------------------------------------------------------------------------------
/Examples/Sum/Program.cs:
--------------------------------------------------------------------------------
1 | // copyright discretelogics 2012. released under the gpl v3. see license.txt for details.
2 | using System;
3 | using System.Diagnostics;
4 | using System.Linq;
5 | using TeaTime;
6 |
7 | namespace ACME.Examples
8 | {
9 | class Program
10 | {
11 | static void Main(string[] args)
12 | {
13 | try
14 | {
15 | if (args.Count() < 1) throw new Exception("Usage: Sum [m]emorymapped");
16 | string filename = args[0];
17 | bool memoryMapped = args.Count() >= 2
18 | ? args[1].StartsWith("m", StringComparison.InvariantCultureIgnoreCase)
19 | : false;
20 |
21 | var sw = Stopwatch.StartNew();
22 | double sum;
23 | if (memoryMapped)
24 | {
25 | sum = RunMemoryMapped(filename);
26 | }
27 | else
28 | {
29 | sum = Run(filename);
30 | }
31 | sw.Stop();
32 | Console.WriteLine("sum=" + sum);
33 | Console.WriteLine("execution time = " + sw.Elapsed.TotalMilliseconds + "ms");
34 | }
35 | catch (Exception ex)
36 | {
37 | Console.WriteLine(ex.Message);
38 | }
39 | }
40 |
41 | static double Run(string filename)
42 | {
43 | using (var tf = TeaFile.OpenRead(filename))
44 | {
45 | return tf.Items.Sum(item => item.Price);
46 | }
47 | }
48 |
49 | static unsafe double RunMemoryMapped(string filename)
50 | {
51 | double sum = 0;
52 | using (var fm = TeaFile.OpenRawMemoryMapping(filename))
53 | {
54 | for (Tick* tick = (Tick*)fm.ItemAreaStart; tick != fm.ItemAreaEnd; ++tick)
55 | {
56 | sum += tick->Price;
57 | }
58 | }
59 | return sum;
60 | }
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/Examples/Sum/Sum.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Debug
5 | x86
6 | 8.0.30703
7 | 2.0
8 | {33331A44-5C87-4931-9B34-C1B4A490DBFA}
9 | Exe
10 | Properties
11 | ACME.Examples
12 | Sum
13 | v4.7.2
14 |
15 |
16 | 512
17 |
18 |
19 | true
20 | ..\..\Bin\
21 | DEBUG;TRACE
22 | full
23 | AnyCPU
24 | ..\..\Bin\Sum.exe.CodeAnalysisLog.xml
25 | true
26 | GlobalSuppressions.cs
27 | prompt
28 | MinimumRecommendedRules.ruleset
29 | ;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets
30 | true
31 | ;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules
32 | true
33 | true
34 | false
35 |
36 |
37 | ..\..\Bin\
38 |
39 |
40 | true
41 | pdbonly
42 | AnyCPU
43 | ..\..\Bin\Sum.exe.CodeAnalysisLog.xml
44 | true
45 | GlobalSuppressions.cs
46 | prompt
47 | MinimumRecommendedRules.ruleset
48 | ;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets
49 | true
50 | ;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules
51 | true
52 | false
53 | true
54 | false
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 | {1CADE377-2821-480D-A0E7-34F224886AF6}
71 | TeaFiles
72 |
73 |
74 | {DD952649-AD45-4B89-B87E-28F0B876171E}
75 | ItemTypes
76 |
77 |
78 |
79 |
80 |
81 |
82 |
89 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2012-present Thomas Hulka
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/Lib/Moq.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/discretelogics/TeaFiles.Net-Time-Series-Storage-in-Files/7a0aef4ed5fda31fdfcd45e1ca565977a4315530/Lib/Moq.dll
--------------------------------------------------------------------------------
/Lib/SharpTestsEx.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/discretelogics/TeaFiles.Net-Time-Series-Storage-in-Files/7a0aef4ed5fda31fdfcd45e1ca565977a4315530/Lib/SharpTestsEx.dll
--------------------------------------------------------------------------------
/Normal.testsettings:
--------------------------------------------------------------------------------
1 |
2 |
3 | These are default test settings for a local test run.
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | TeaFiles.Net - Time Series Storage in Files
2 | ===========================================
3 |
4 | Use TeaFiles.Net to create, read and write files holding time series data.
5 |
6 |
7 |
8 | Features
9 | --------
10 |
11 | * highest **performance**
12 | * very **simple**
13 | * **versatile** - open TeaFiles with C++, C#, Python, R, on any platform
14 |
15 |
16 |
17 | TeaFiles = Binary Data + Header
18 | -------------------------------
19 |
20 | * TeaFile is a **file format**
21 | * to store **time series**
22 | * as binary **flat files**
23 | * optional **header** holds a **description** of file contents (metadata)
24 | * including a description of the **item type layout** (schema)
25 | * simple format, designed to make API writing very easy
26 | * http://www.discretelogics.com published the file format and
27 | * releases APIs for C#, C++, Python under the GPL
28 |
29 |
30 |
31 | Performance
32 | -----------
33 | > 250 Mio Items per seconds cold
34 | > 465 Mio Items per seconds warm
35 |
36 | benchmark results at http://www.discretelogics.com/resources/benchmarks/teafilesbm.htm
37 |
38 |
39 |
40 | Installation
41 | ------------
42 |
43 | * Get the NuGet package from nuget.org/packages/TeaFiles.Net or
44 |
45 |
46 | Documentation
47 | -------------
48 |
49 | The API class documentation is available online at www.discretelogics.com/doc/teafiles.net
50 |
51 | TeaTime product family
52 | ----------------------
53 |
54 | TeaFiles are the foundation of the TeaTime product family, the toolset for persistence, visualisation and real time analysis of time series.
55 |
56 | Related products:
57 | * [TeaShell](http://www.discretelogics.com/teashell) - Browse Time Series like Photos
58 |
59 | Examples
60 | --------
61 |
62 | ```C#
63 | // define time series item type
64 | struct Tick
65 | {
66 | public Time Time;
67 | public double Price;
68 | public int Volume;
69 | }
70 | // create file and write values
71 | using (var tf = TeaFile.Create("acme.tea"))
72 | {
73 | tf.Write(new Tick { Price = 5, Time = DateTime.Now, Volume = 700 });
74 | tf.Write(new Tick { Price = 15, Time = DateTime.Now.AddHours(1), Volume = 1700 });
75 | // ...
76 | }
77 | // sum the prices of all items in the file
78 | using (var tf = TeaFile.OpenRead("acme.tea"))
79 | {
80 | return tf.Items.Sum(item => item.Price);
81 | }
82 | ```
83 |
84 | License
85 | -------
86 |
87 | Released under the MIT license.
88 |
89 | Thanks
90 | ------
91 |
92 | to contributors @larstbone and @SabotageAndi
93 |
--------------------------------------------------------------------------------
/TeaFiles.Test/Access/ItemCollectionTest.cs:
--------------------------------------------------------------------------------
1 | // copyright discretelogics 2012. released under the gpl v3. see license.txt for details.
2 | using System.Collections;
3 | using System.Globalization;
4 | using System.Linq;
5 | using System.Threading;
6 | using Microsoft.VisualStudio.TestTools.UnitTesting;
7 | using Moq;
8 | using SharpTestsEx;
9 |
10 | namespace TeaTime
11 | {
12 | [TestClass]
13 | public class ItemCollectionTest
14 | {
15 | [TestInitialize]
16 | public void Init()
17 | {
18 | // Ensure english error messages on non english systems.
19 | Thread.CurrentThread.CurrentUICulture = new CultureInfo("en-US");
20 | }
21 |
22 | [TestMethod]
23 | public void ExoticCoverage()
24 | {
25 | var r = new Mock(MockBehavior.Strict);
26 | var collection = new ItemCollection(r.Object);
27 | IEnumerable enumerable = collection;
28 | enumerable.GetEnumerator().Should().Not.Be.Null();
29 | }
30 |
31 | [TestMethod]
32 | public void GetEnumeratorTest()
33 | {
34 | var filename = "ItemCollectionTest_GetEnumeratorTest.tea";
35 | using (var tf = TeaFile.Create(filename))
36 | {
37 | tf.Write(Enumerable.Range(2, 4));
38 | }
39 | using (var tf = TeaFile.OpenRead(filename))
40 | {
41 | var e = tf.Items.GetEnumerator(0);
42 | e.MoveNext().Should().Be.True();
43 | e.Current.Values[0].Should().Be(2);
44 | e.MoveNext().Should().Be.True();
45 | e.Current.Values[0].Should().Be(3);
46 | e.MoveNext().Should().Be.True();
47 | e.Current.Values[0].Should().Be(4);
48 | e.MoveNext().Should().Be.True();
49 | e.Current.Values[0].Should().Be(5);
50 | e.MoveNext().Should().Be.False();
51 |
52 | e = tf.Items.GetEnumerator(2);
53 | e.MoveNext().Should().Be.True();
54 | e.Current.Values[0].Should().Be(4);
55 | e.MoveNext().Should().Be.True();
56 | e.Current.Values[0].Should().Be(5);
57 | e.MoveNext().Should().Be.False();
58 | }
59 | }
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/TeaFiles.Test/Access/ManagedMemoryMappingTest.cs:
--------------------------------------------------------------------------------
1 | // copyright discretelogics 2012. released under the gpl v3. see license.txt for details.
2 | using System;
3 | using System.Globalization;
4 | using System.Threading;
5 | using Microsoft.VisualStudio.TestTools.UnitTesting;
6 | using SharpTestsEx;
7 |
8 | namespace TeaTime
9 | {
10 | [TestClass]
11 | public class MemoryMappedAccessTest
12 | {
13 | [TestInitialize]
14 | public void Init()
15 | {
16 | // Ensure english error messages on non english systems.
17 | Thread.CurrentThread.CurrentUICulture = new CultureInfo("en-US");
18 | }
19 |
20 | [TestMethod]
21 | public void AccessItemsViaMemoryMapping()
22 | {
23 | var filename = "MemoryMappedAccessTest_AccessItemsViaMemoryMapping.tea";
24 | using (var f = TeaFile>.Create(filename))
25 | {
26 | var dt = new DateTime(2000, 1, 1);
27 | for (int i = 0; i < 27; i++)
28 | {
29 | f.Write(new Event {Time = dt.AddDays(i), Value = i * 10});
30 | }
31 | }
32 | using (var view = TeaFile>.OpenMemoryMapping(filename))
33 | {
34 | Event e = view.Read(0);
35 | e.Value.Should().Be(0);
36 | e.Time.Should().Be(new DateTime(2000, 1, 1));
37 |
38 | e = view.Read(0);
39 | e.Value.Should().Be(0);
40 | e.Time.Should().Be(new DateTime(2000, 1, 1));
41 |
42 | e = view.Read(1);
43 | e.Value.Should().Be(10);
44 | e.Time.Should().Be(new DateTime(2000, 1, 2));
45 |
46 | e = view.Read(2);
47 | e.Value.Should().Be(20);
48 | e.Time.Should().Be(new DateTime(2000, 1, 3));
49 |
50 | var t = new DateTime(2000, 1, 1);
51 | for (int i = 0; i < 27; i++)
52 | {
53 | e = view.Read(i);
54 | e.Value.Should().Be(i * 10);
55 | e.Time.Should().Be(t.AddDays(i));
56 | e.Should().Be(view[i]);
57 | }
58 | }
59 | }
60 |
61 | [TestMethod]
62 | public void ReadingBeyondEntOfItemArea()
63 | {
64 | var filename = "MemoryMappedAccessTest_ReadingBeyondEntOfItemArea.tea";
65 | using (var f = TeaFile>.Create(filename))
66 | {
67 | Time t = new DateTime(2000, 1, 1);
68 | 3.Times(() => f.Write(new Event {Time = t, Value = 777}));
69 | }
70 | using (var view = TeaFile>.OpenMemoryMapping(filename))
71 | {
72 | view.Read(0);
73 | view.Read(1);
74 | view.Read(2);
75 | Executing.This(() => view.Read(3)).Should().Throw();
76 | }
77 | }
78 | }
79 | }
80 |
--------------------------------------------------------------------------------
/TeaFiles.Test/Access/RawMemoryMappingTest.cs:
--------------------------------------------------------------------------------
1 | // copyright discretelogics 2012. released under the gpl v3. see license.txt for details.
2 | using System;
3 | using System.Globalization;
4 | using System.Threading;
5 | using Microsoft.VisualStudio.TestTools.UnitTesting;
6 | using SharpTestsEx;
7 | using TeaTime.SampleItems;
8 |
9 | namespace TeaTime.Access
10 | {
11 | [TestClass]
12 | public class RawMemoryMappingTest
13 | {
14 | [TestInitialize]
15 | public void Init()
16 | {
17 | // Ensure english error messages on non english systems.
18 | Thread.CurrentThread.CurrentUICulture = new CultureInfo("en-US");
19 | }
20 |
21 | [TestMethod]
22 | public unsafe void AccessItemsViaMemoryMapping()
23 | {
24 | const string filename = "RawMemoryMappingTest_AccessItemsViaMemoryMapping.tea";
25 | using (var f = TeaFile.Create(filename))
26 | {
27 | var dt = new DateTime(2000, 1, 1);
28 | for (int i = 0; i < 27; i++)
29 | {
30 | f.Write(new Tick {Time = dt.AddDays(i), Volume = i * 10});
31 | }
32 | }
33 | using (var view = TeaFile.OpenRawMemoryMapping(filename))
34 | {
35 | Tick* tick = (Tick*)view.ItemAreaStart;
36 | var dt = new DateTime(2000, 1, 1);
37 | for (int i = 0; i < 27; i++)
38 | {
39 | tick->Volume.Should().Be(i * 10);
40 | tick->Time.Should().Be(dt.AddDays(i));
41 | tick++;
42 | }
43 | }
44 | }
45 |
46 | [TestMethod]
47 | public unsafe void AccessItemsViaMemoryMappingPointers()
48 | {
49 | const string filename = "AccessItemsViaMemoryMappingPointers.tea";
50 | using (var f = TeaFile.Create(filename))
51 | {
52 | var dt = new DateTime(2000, 1, 1);
53 | for (int i = 0; i < 3; i++)
54 | {
55 | f.Write(new Tick { Time = dt.AddDays(i), Volume = i * 10 });
56 | }
57 | }
58 | using (var view = TeaFile.OpenRawMemoryMapping(filename))
59 | {
60 | Tick* tick = (Tick*)view.ItemAreaStart;
61 | Tick* end = (Tick*)view.ItemAreaEnd;
62 | ((int)tick).Should().Be.LessThanOrEqualTo((int)end);
63 |
64 | int i = 0;
65 | var dt = new DateTime(2000, 1, 1);
66 | while(tick < end)
67 | {
68 | tick->Volume.Should().Be(i * 10);
69 | tick->Time.Should().Be(dt.AddDays(i));
70 | tick++;
71 | i++;
72 | }
73 | }
74 | }
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/TeaFiles.Test/Access/SafeBufferTest.cs:
--------------------------------------------------------------------------------
1 | // copyright discretelogics 2012. released under the gpl v3. see license.txt for details.
2 | using Microsoft.VisualStudio.TestTools.UnitTesting;
3 |
4 | namespace TeaTime
5 | {
6 | [TestClass]
7 | public class SafeBufferTest
8 | {
9 | // tests adopted from CppUtilsTest
10 | //[TestMethod]
11 | //unsafe public void WriteStructIntoFileTest()
12 | //{
13 | // using (var f = new FileStream("test", FileMode.Create))
14 | // {
15 | // var u = new CppUtils(f);
16 | // A a = new A() { d = 1.7, i16 = 1, ui8 = 32 };
17 | // u.Write(a);
18 | // Assert.AreEqual(sizeof(A), f.Position);
19 | // }
20 | //}
21 |
22 | //[TestMethod]
23 | //unsafe public void WriteAndReadStructIntoFileTest()
24 | //{
25 | // using (var f = new FileStream("test", FileMode.Create))
26 | // {
27 | // var u = new CppUtils(f);
28 | // A a = new A() { d = 1.7, i16 = 1, ui8 = 32 };
29 | // u.Write(a);
30 | // f.Position = 0; // rewind
31 | // A aa = u.Read();
32 | // Assert.AreEqual(aa, a);
33 | // }
34 | //}
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/TeaFiles.Test/Base/EventTest.cs:
--------------------------------------------------------------------------------
1 | // copyright discretelogics 2012. released under the gpl v3. see license.txt for details.
2 | using System;
3 | using System.Globalization;
4 | using System.Threading;
5 | using Microsoft.VisualStudio.TestTools.UnitTesting;
6 | using SharpTestsEx;
7 |
8 | namespace TeaTime
9 | {
10 | [TestClass]
11 | public class EventTest
12 | {
13 | [TestInitialize]
14 | public void Init()
15 | {
16 | // Ensure english error messages on non english systems.
17 | Thread.CurrentThread.CurrentUICulture = new CultureInfo("en-US");
18 | }
19 |
20 | [TestMethod]
21 | public void EventToString()
22 | {
23 | Event e = new Event();
24 | e.Time = new Time(2000, 1, 2);
25 | e.Value = 172;
26 |
27 | string datetString = new DateTime(2000, 1, 2).ToString();
28 | e.ToString().Should().Be(datetString + "\t172");
29 | Console.WriteLine(e);
30 | }
31 |
32 | [TestMethod]
33 | public void EventCtorTest()
34 | {
35 | var t = new DateTime(2000, 1, 2);
36 | Event e = new Event(t, 72);
37 | e.Value.Should().Be(72);
38 | e.Time.Should().Be(t);
39 | }
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/TeaFiles.Test/Base/NameValueTest.cs:
--------------------------------------------------------------------------------
1 | // copyright discretelogics 2012. released under the gpl v3. see license.txt for details.
2 | using System;
3 | using System.Collections;
4 | using System.Globalization;
5 | using System.Linq;
6 | using System.Threading;
7 | using Microsoft.VisualStudio.TestTools.UnitTesting;
8 | using SharpTestsEx;
9 |
10 | namespace TeaTime
11 | {
12 | [TestClass]
13 | public class NameValueTest
14 | {
15 | [TestInitialize]
16 | public void Init()
17 | {
18 | // Ensure english error messages on non english systems.
19 | Thread.CurrentThread.CurrentUICulture = new CultureInfo("en-US");
20 | }
21 |
22 | [TestMethod]
23 | public void ExoticCoverage()
24 | {
25 | Executing.This(() => new NameValue("astring", null)).Should().Throw();
26 | Executing.This(() => new NameValue(null, 1)).Should().Throw();
27 | Executing.This(() => new NameValue(null, 1.23)).Should().Throw();
28 | Executing.This(() => new NameValue(null, "duffy duck")).Should().Throw();
29 | Executing.This(() => new NameValue(null, Guid.Empty)).Should().Throw();
30 |
31 | var nvc = new NameValueCollection();
32 | IEnumerable enumerable = nvc;
33 | enumerable.GetEnumerator().Should().Not.Be.Null();
34 | }
35 |
36 | [TestMethod]
37 | public void NameValueCollectionAdd()
38 | {
39 | NameValueCollection nvc = new NameValueCollection();
40 | nvc.Add("anint", 17);
41 | nvc.Add("adouble", 1.234);
42 | nvc.Add("astring", "bugs bunny");
43 | nvc.Add("aguid", Guid.Empty);
44 |
45 | nvc.Count.Should().Be(4);
46 |
47 | nvc.GetValue("anint").Should().Be(17);
48 | nvc.GetValue("adouble").Should().Be(1.234);
49 | nvc.GetValue("astring").Should().Be("bugs bunny");
50 | nvc.GetValue("aguid").Should().Be(Guid.Empty);
51 |
52 | int i = 1;
53 | 10.Times(() => nvc.Add("x" + i, i++));
54 |
55 | nvc.ToString().Should().Contain("anint");
56 | nvc.ToString().Should().Contain("17");
57 | nvc.ToString().Should().Contain("adouble");
58 | nvc.ToString().Should().Contain("bugs bunny");
59 | nvc.ToString().Should().Contain("aguid");
60 | nvc.ToString().Should().Contain("...");
61 | }
62 |
63 | [TestMethod]
64 | public void ValueTextTest()
65 | {
66 | string s = new NameValue("name", 1.23).ValueText;
67 | (s == "1.23" || s == "1,23").Should().Be.True(); // comma will be either . or ,
68 |
69 | new NameValue("name", "bugs bunny").ValueText.Should().Be("bugs bunny");
70 | new NameValue("name", Guid.Empty).ValueText.Should().Be(Guid.Empty.ToString());
71 | }
72 |
73 | [TestMethod]
74 | public void NameValueCollectionFactoryTest()
75 | {
76 | var nvc = NameValueCollection.From("aname", 42, "bname", Guid.Empty, "cname", "cvalue", "dname", 12.34);
77 | nvc.Count.Should().Be(4);
78 | nvc.Select(nv => nv.Name).Should().Have.SameSequenceAs("aname", "bname", "cname", "dname");
79 | nvc.Select(nv => nv.Kind).Should().Have.SameSequenceAs(NameValue.ValueKind.Int32, NameValue.ValueKind.Guid, NameValue.ValueKind.Text, NameValue.ValueKind.Double);
80 | nvc.Select(nv => nv.ValueText).Should().Have.SameSequenceAs("42", Guid.Empty.ToString(), "cvalue", 12.34.ToString());
81 | }
82 |
83 | [TestMethod]
84 | public void NameValueCollectionFactoryExceptions()
85 | {
86 | Executing.This(() => NameValueCollection.From(111, 42)).Should().Throw();
87 | Executing.This(() => NameValueCollection.From(111, 42, 11)).Should().Throw();
88 | }
89 |
90 | [TestMethod]
91 | public void NameValueShouldNeverHaveNullValueTest()
92 | {
93 | Executing.This(() => new NameValue("name1", null)).Should().Throw();
94 | }
95 | }
96 | }
97 |
--------------------------------------------------------------------------------
/TeaFiles.Test/Base/TimeScaleTest.cs:
--------------------------------------------------------------------------------
1 | // copyright discretelogics 2012. released under the gpl v3. see license.txt for details.
2 | using System;
3 | using System.Globalization;
4 | using System.Threading;
5 | using Microsoft.VisualStudio.TestTools.UnitTesting;
6 | using SharpTestsEx;
7 |
8 | namespace TeaTime
9 | {
10 | [TestClass]
11 | public class TimeScaleTest
12 | {
13 | [TestInitialize]
14 | public void Init()
15 | {
16 | // Ensure english error messages on non english systems.
17 | Thread.CurrentThread.CurrentUICulture = new CultureInfo("en-US");
18 | }
19 |
20 | [TestMethod]
21 | public void ExoticCoverage()
22 | {
23 | Timescale.Java.GetHashCode().Should().Not.Be.EqualTo(Timescale.Net.GetHashCode()); // otherwise our Hashcode generation would be questionable
24 | Executing.This(() => Timescale.FromEpoch(1, TimeSpan.TicksPerDay * 2)).Should().Throw();
25 | Executing.This(() => Timescale.FromEpoch(1, 1, 1, TimeSpan.TicksPerDay * 2)).Should().Throw();
26 | }
27 |
28 | [TestMethod]
29 | public void TickScaleTest1to1()
30 | {
31 | var scale = Timescale.FromEpoch(1, 1, 1, TimeSpan.TicksPerDay);
32 | scale.Epoch.Should().Be(0);
33 | scale.TicksPerDay.Should().Be(TimeSpan.TicksPerDay);
34 | scale.NetToScale(1234567).Should().Be(1234567);
35 | scale.ScaleToNet(1234567).Should().Be(1234567);
36 | }
37 |
38 | [TestMethod]
39 | public void TickScaleTest1to7()
40 | {
41 | var scale = Timescale.FromEpoch(1, 1, 1, TimeSpan.TicksPerDay / 7);
42 | scale.Epoch.Should().Be(0);
43 | scale.TicksPerDay.Should().Be(TimeSpan.TicksPerDay / 7);
44 | scale.NetToScale(1234567).Should().Be(1234567 / 7);
45 | scale.ScaleToNet(1234567).Should().Be(1234567 * 7);
46 | }
47 |
48 | [TestMethod]
49 | public void Equality()
50 | {
51 | (Timescale.Java == Timescale.Net).Should().Be.False();
52 | (Timescale.Java != Timescale.Net).Should().Be.True();
53 | Timescale.Java.Equals(711).Should().Be.False();
54 | }
55 |
56 | [TestMethod]
57 | public void WellknownNames()
58 | {
59 | Timescale.Net.WellKnownName.Should().Be("Net");
60 | Timescale.Java.WellKnownName.Should().Be("Java");
61 | Timescale.FromEpoch(222, 33).WellKnownName.Should().Be("Custom");
62 | }
63 |
64 | [TestMethod]
65 | public void ToStringTest()
66 | {
67 | Timescale.Net.ToString().Should().Be("Net");
68 | Timescale.Java.ToString().Should().Be("Java");
69 | Timescale.FromEpoch(1000, 1).ToString().Should().Be("1000,1");
70 | }
71 |
72 | [TestMethod]
73 | public void UsingJavaTime()
74 | {
75 | Time.Scale = Timescale.Java;
76 |
77 | Time t = new Time(2012, 1, 2); // use Time the same way as you use DateTime
78 | DateTime dt = t; // implicit conversion
79 |
80 | // all logical values are the same
81 | t.Year.Should().Be(dt.Year);
82 | t.Month.Should().Be(dt.Month);
83 | t.Day.Should().Be(dt.Day);
84 | t.Hour.Should().Be(dt.Hour);
85 | t.Minute.Should().Be(dt.Minute);
86 | t.Second.Should().Be(dt.Second);
87 |
88 | // but the Tick representation is different
89 | t.Ticks.Should().Be.LessThan(dt.Ticks); // TeaTime.Time.Ticks < System.DateTime.Ticks
90 | }
91 |
92 | [TestMethod]
93 | public void UsingNetTime()
94 | {
95 | Time.Scale = Timescale.Net; // <- using System.DateTime Tick representation
96 |
97 | // as in the previous example
98 | Time t = new Time(2012, 1, 2);
99 | DateTime dt = t;
100 | t.Year.Should().Be(dt.Year);
101 | t.Month.Should().Be(dt.Month);
102 | t.Day.Should().Be(dt.Day);
103 | t.Hour.Should().Be(dt.Hour);
104 | t.Minute.Should().Be(dt.Minute);
105 | t.Second.Should().Be(dt.Second);
106 |
107 | // now, Ticks are equal!
108 | t.Ticks.Should().Be.EqualTo(dt.Ticks); // TeaTime.Time.Ticks == System.DateTime.Ticks
109 | }
110 |
111 | [TestMethod]
112 | public void JavaScaleValueTest()
113 | {
114 | Time.Scale = Timescale.Java;
115 | Time t = new Time(1970, 1, 3);
116 | t.Ticks.Should().Be(2 * 86400 * 1000);
117 | }
118 |
119 | [TestMethod]
120 | public void DateTimeToTimeConversionConsidersScale()
121 | {
122 | Time.Scale = Timescale.Java;
123 | Time t = new DateTime(1970, 1, 3);
124 | t.Ticks.Should().Be(2 * 86400 * 1000);
125 | }
126 | }
127 | }
128 |
--------------------------------------------------------------------------------
/TeaFiles.Test/Description/DescriptionTest.cs:
--------------------------------------------------------------------------------
1 | // copyright discretelogics 2012. released under the gpl v3. see license.txt for details.
2 | using System.IO;
3 | using Microsoft.VisualStudio.TestTools.UnitTesting;
4 | using SharpTestsEx;
5 |
6 | namespace TeaTime
7 | {
8 | [TestClass]
9 | public class DescriptionTest
10 | {
11 | [TestMethod]
12 | public void DescriptionOfZeroFileIsNotNull()
13 | {
14 | var filename = "DescriptionTest_DescriptionOfZeroFileIsNotNull.tea";
15 | using (TeaFile.Create(filename))
16 | {
17 | }
18 | using (var tf = TeaFile.OpenRead(filename))
19 | {
20 | tf.Description.Should().Not.Be.Null();
21 | }
22 | }
23 |
24 | public struct StructA
25 | {
26 | public byte A;
27 | public double B;
28 | }
29 |
30 | [TestMethod]
31 | public void IsTimeSeriesFalse()
32 | {
33 | var stream = new MemoryStream();
34 | using (var tf = TeaFile.Create(stream))
35 | {
36 | var d = tf.Description;
37 | d.ItemDescription.HasEventTime.Should().Be.False();
38 | }
39 | }
40 |
41 | [TestMethod]
42 | public void IsTimeSeriesTrue()
43 | {
44 | var stream = new MemoryStream();
45 | using (var tf = TeaFile>.Create(stream))
46 | {
47 | var d = tf.Description;
48 | d.ItemDescription.HasEventTime.Should().Be.True();
49 | }
50 | }
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/TeaFiles.Test/Description/FieldTest.cs:
--------------------------------------------------------------------------------
1 | // copyright discretelogics 2012. released under the gpl v3. see license.txt for details.
2 | using System;
3 | using System.Linq;
4 | using Microsoft.VisualStudio.TestTools.UnitTesting;
5 | using SharpTestsEx;
6 | using TeaTime.SampleItems;
7 |
8 | namespace TeaTime
9 | {
10 | [TestClass]
11 | public class FieldTest
12 | {
13 | [TestMethod]
14 | public void ExoticCoverage()
15 | {
16 | var f = new Field();
17 | Executing.This(() => f.GetValue(null)).Should().Throw();
18 | }
19 |
20 | [TestMethod]
21 | public void GetValueTest()
22 | {
23 | var filename = "FieldTest_GetValueTest.tea";
24 | using (var tf = TeaFile.Create(filename))
25 | {
26 | tf.Write(Enumerable.Range(1, 10).Select(i => new OHLCV {Close = i * 101}));
27 | }
28 | using (var tf = TeaFile.OpenRead(filename))
29 | {
30 | var id = tf.Description.ItemDescription;
31 | var field = id.Fields.First(ff => ff.Name == "Close");
32 |
33 | Item item = tf.Items.First();
34 | field.GetValue(item).Should().Be(101.0);
35 |
36 | item = tf.Items[3];
37 | field.GetValue(item).Should().Be(404.0);
38 | }
39 | }
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/TeaFiles.Test/Description/ItemDescriptionDetailsTest.cs:
--------------------------------------------------------------------------------
1 | // copyright discretelogics 2012. released under the gpl v3. see license.txt for details.
2 | using System.Globalization;
3 | using System.Threading;
4 | using Microsoft.VisualStudio.TestTools.UnitTesting;
5 | using SharpTestsEx;
6 |
7 | namespace TeaTime
8 | {
9 | [TestClass]
10 | public class ItemDescriptionDetailsTest
11 | {
12 | [TestInitialize]
13 | public void Init()
14 | {
15 | // Ensure english error messages on non english systems.
16 | Thread.CurrentThread.CurrentUICulture = new CultureInfo("en-US");
17 | }
18 |
19 | [TestMethod]
20 | public void Usage()
21 | {
22 | var allButNoName = ItemDescriptionElements.All & ~ItemDescriptionElements.ItemName;
23 | allButNoName.HasFlag(ItemDescriptionElements.ItemName).Should().Be.False();
24 | allButNoName.HasFlag(ItemDescriptionElements.ItemSize).Should().Be.True();
25 | allButNoName.HasFlag(ItemDescriptionElements.FieldOffsets).Should().Be.True();
26 | allButNoName.HasFlag(ItemDescriptionElements.FieldNames).Should().Be.True();
27 | allButNoName.HasFlag(ItemDescriptionElements.FieldTypes).Should().Be.True();
28 | }
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/TeaFiles.Test/Description/TeaTypeTest.cs:
--------------------------------------------------------------------------------
1 | // copyright discretelogics 2012. released under the gpl v3. see license.txt for details.
2 | using System;
3 | using System.Globalization;
4 | using System.Threading;
5 | using Microsoft.VisualStudio.TestTools.UnitTesting;
6 | using SharpTestsEx;
7 |
8 | namespace TeaTime
9 | {
10 | [TestClass]
11 | public class TeaTypeTest
12 | {
13 | [TestInitialize]
14 | public void Init()
15 | {
16 | // Ensure english error messages on non english systems.
17 | Thread.CurrentThread.CurrentUICulture = new CultureInfo("en-US");
18 | }
19 |
20 | [TestMethod]
21 | public void TeaTypeMapping()
22 | {
23 | typeof (SByte).GetFieldType().Should().Be(FieldType.Int8);
24 | typeof (Int16).GetFieldType().Should().Be(FieldType.Int16);
25 | typeof (Int32).GetFieldType().Should().Be(FieldType.Int32);
26 | typeof (Int64).GetFieldType().Should().Be(FieldType.Int64);
27 |
28 | typeof (Byte).GetFieldType().Should().Be(FieldType.UInt8);
29 | typeof (UInt16).GetFieldType().Should().Be(FieldType.UInt16);
30 | typeof (UInt32).GetFieldType().Should().Be(FieldType.UInt32);
31 | typeof (UInt64).GetFieldType().Should().Be(FieldType.UInt64);
32 |
33 | typeof (float).GetFieldType().Should().Be(FieldType.Float);
34 | typeof (double).GetFieldType().Should().Be(FieldType.Double);
35 |
36 | typeof (Time).GetFieldType().Should().Be(FieldType.Int64);
37 |
38 | typeof (decimal).GetFieldType().Should().Be(FieldType.NetDecimal);
39 |
40 | Executing.This(() => typeof (DateTime).GetFieldType()).Should().Throw();
41 | Executing.This(() => typeof (string).GetFieldType()).Should().Throw();
42 | }
43 |
44 | [TestMethod]
45 | public void TeaTypeSize()
46 | {
47 | typeof (SByte).GetFieldType().GetSize().Should().Be(sizeof (SByte));
48 | typeof (Int16).GetFieldType().GetSize().Should().Be(sizeof (Int16));
49 | typeof (Int32).GetFieldType().GetSize().Should().Be(sizeof (Int32));
50 | typeof (Int64).GetFieldType().GetSize().Should().Be(sizeof (Int64));
51 |
52 | typeof (Byte).GetFieldType().GetSize().Should().Be(sizeof (byte));
53 | typeof (UInt16).GetFieldType().GetSize().Should().Be(sizeof (UInt16));
54 | typeof (UInt32).GetFieldType().GetSize().Should().Be(sizeof (UInt32));
55 | typeof (UInt64).GetFieldType().GetSize().Should().Be(sizeof (UInt64));
56 |
57 | typeof (float).GetFieldType().GetSize().Should().Be(sizeof (float));
58 | typeof (double).GetFieldType().GetSize().Should().Be(sizeof (double));
59 |
60 | typeof (decimal).GetFieldType().GetSize().Should().Be(sizeof (decimal));
61 |
62 | Executing.This(() => FieldType.None.GetSize()).Should().Throw();
63 | Executing.This(() => ((FieldType)777).GetSize()).Should().Throw();
64 | }
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/TeaFiles.Test/ExtensionsTest.cs:
--------------------------------------------------------------------------------
1 | // copyright discretelogics 2012. released under the gpl v3. see license.txt for details.
2 | using System;
3 | using System.Collections.Generic;
4 | using System.IO;
5 | using System.Linq;
6 | using System.Reflection;
7 | using Microsoft.VisualStudio.TestTools.UnitTesting;
8 | using SharpTestsEx;
9 |
10 | namespace TeaTime
11 | {
12 | [TestClass]
13 | public class ExtensionsTest
14 | {
15 | [TestMethod]
16 | public void ToSafeStringTest()
17 | {
18 | 7.SafeToString("o is null").Should().Be(7.ToString());
19 |
20 | object o = null;
21 | o.SafeToString("o is null").Should().Be("o is null");
22 | }
23 |
24 | [TestMethod]
25 | public void ToSafeStringEmptyTest()
26 | {
27 | 7.SafeToString().Should().Be(7.ToString());
28 |
29 | object o = null;
30 | o.SafeToString().Should().Be("empty");
31 | }
32 |
33 | [TestMethod]
34 | public void IsDefinedTest()
35 | {
36 | MethodBase.GetCurrentMethod().IsDefined().Should().Be.True();
37 | MethodBase.GetCurrentMethod().IsDefined().Should().Be.False();
38 | }
39 |
40 | [TestMethod]
41 | public void TimesTest()
42 | {
43 | int n = 0;
44 | 0.Times(() => n++);
45 | n.Should().Be(0);
46 |
47 | 3.Times(() => n++);
48 | n.Should().Be(3);
49 | }
50 |
51 | struct Test
52 | {
53 | public string S;
54 | public int N;
55 | }
56 |
57 | [TestMethod]
58 | public void ToStringFromFieldsTest()
59 | {
60 | Test t = new Test {S = "s", N = 71};
61 | t.ToStringFromFields("#").Should().Be("S=s#N=71");
62 | }
63 |
64 | [TestMethod]
65 | public void ToStringFromFieldsDefaultTest()
66 | {
67 | Test t = new Test {S = "s", N = 71};
68 | t.ToStringFromFields().Should().Be("S=s N=71");
69 | }
70 |
71 | [TestMethod]
72 | public void FormattedTest()
73 | {
74 | "{0} => {1}".Formatted(42, 71).Should().Be("42 => 71");
75 | }
76 |
77 | [TestMethod]
78 | public void JoinedTest()
79 | {
80 | var arr = new[] {2, 3, 5};
81 | arr.Joined("-").Should().Be("2-3-5");
82 | }
83 |
84 | [TestMethod]
85 | public void GetFirstPartTest()
86 | {
87 | "123456".GetFirstPart('4').Should().Be("123");
88 | "123456".GetFirstPart('9').Should().Be("123456");
89 | "".GetFirstPart('9').Should().Be("");
90 | }
91 |
92 | [TestMethod]
93 | public void ForEachTest()
94 | {
95 | int i = 0;
96 | IEnumerable e = new[] {1.1, 2.2, 3.3};
97 | var list = e.ToList();
98 | e.ForEach((v) => v.Should().Be(list[i++]));
99 | }
100 |
101 | [TestMethod]
102 | public void ReadTeaType()
103 | {
104 | var ms = new MemoryStream();
105 | var w = new BinaryWriter(ms);
106 | w.Write((byte)11);
107 | w.Write((UInt16)22);
108 | w.Write(33);
109 | w.Write((UInt64)44L);
110 | w.Write((sbyte)-11);
111 | w.Write((short)-22);
112 | w.Write(-33);
113 | w.Write(-44L);
114 | w.Write(7.22f);
115 | w.Write(1.23d);
116 | w.Write(12345m);
117 |
118 | ms.Position = 0;
119 | var r = new BinaryReader(ms);
120 | r.Read(FieldType.UInt8).Should().Be((byte)11);
121 | r.Read(FieldType.UInt16).Should().Be((UInt16)22u);
122 | r.Read(FieldType.UInt32).Should().Be(33u);
123 | r.Read(FieldType.UInt64).Should().Be(44Lu);
124 |
125 | r.Read(FieldType.Int8).Should().Be((sbyte)-11);
126 | r.Read(FieldType.Int16).Should().Be((Int16)(-22));
127 | r.Read(FieldType.Int32).Should().Be(-33);
128 | r.Read(FieldType.Int64).Should().Be((-44L));
129 |
130 | r.Read(FieldType.Float).Should().Be(7.22f);
131 | r.Read(FieldType.Double).Should().Be(1.23d);
132 | r.Read(FieldType.NetDecimal).Should().Be(12345m);
133 |
134 | Executing.This(() => r.Read((FieldType)777)).Should().Throw();
135 | Executing.This(() => ((BinaryReader)null).Read(FieldType.UInt8)).Should().Throw();
136 | }
137 | }
138 | }
139 |
--------------------------------------------------------------------------------
/TeaFiles.Test/Header/HeaderManagerTest.cs:
--------------------------------------------------------------------------------
1 | // copyright discretelogics 2012. released under the gpl v3. see license.txt for details.
2 | using System;
3 | using System.Globalization;
4 | using System.IO;
5 | using System.Threading;
6 | using Microsoft.VisualStudio.TestTools.UnitTesting;
7 | using Moq;
8 | using SharpTestsEx;
9 | using TeaTime.IO;
10 |
11 | namespace TeaTime.Header
12 | {
13 | [TestClass]
14 | public class HeaderManagerTest
15 | {
16 | [TestInitialize]
17 | public void Init()
18 | {
19 | // get english error messages on non english systems.
20 | Thread.CurrentThread.CurrentUICulture = new CultureInfo("en-US");
21 | }
22 |
23 | //[TestCleanup]
24 | //public void TestTearDown()
25 | //{
26 | // HeaderManager.Instance.Initialized();
27 | //}
28 |
29 | [TestMethod]
30 | public void WriteCoreHeader()
31 | {
32 | var ms = new MemoryStream();
33 | HeaderManager.Instance.WriteHeader(new FormattedWriter(new FileIO(ms)), null);
34 | }
35 |
36 | [TestMethod]
37 | public void CreateSectionsTest()
38 | {
39 | var fw = new Mock(MockBehavior.Strict);
40 | var wc = new WriteContext(fw.Object);
41 | wc.ItemAreaStart.Should().Be(0); // not set yet
42 | HeaderManager.Instance.CreateSections(wc);
43 | wc.ItemAreaStart.Should().Be(32);
44 | }
45 |
46 | [TestMethod]
47 | public void CoreHeaderRoundTrip()
48 | {
49 | var ms = new MemoryStream();
50 | HeaderManager.Instance.WriteHeader(new FormattedWriter(new FileIO(ms)), null);
51 | ms.Length.Should().Be(4 * 8);
52 | ms.Position = 0;
53 | var rc = HeaderManager.Instance.ReadHeader(new FormattedReader(new FileIO(ms)));
54 | rc.Should().Not.Be.Null();
55 | rc.ItemAreaStart.Should().Be(32);
56 | rc.ItemAreaEnd.Should().Be(0);
57 | rc.SectionCount.Should().Be(0);
58 | ms.Position.Should().Be(ms.Length);
59 | }
60 |
61 | [TestMethod]
62 | public void HeaderHasLengthOfItemStart()
63 | {
64 | var ms = new MemoryStream();
65 | var desc = new TeaFileDescription();
66 | desc.ContentDescription = "a";
67 | var wc = HeaderManager.Instance.WriteHeader(new FormattedWriter(new FileIO(ms)), desc);
68 | ms.Length.Should().Be(wc.ItemAreaStart);
69 | ms.Position.Should().Be(wc.ItemAreaStart);
70 | (ms.Position % 8).Should().Be(0);
71 | }
72 |
73 | [TestMethod]
74 | public void HeaderWithContentDescription()
75 | {
76 | var ms = new MemoryStream();
77 | var desc = new TeaFileDescription();
78 | desc.ContentDescription = "a";
79 | var wc = HeaderManager.Instance.WriteHeader(new FormattedWriter(new FileIO(ms)), desc);
80 | ms.Length.Should().Be.GreaterThan(4 * 8);
81 | ms.Position.Should().Be(wc.ItemAreaStart);
82 | (ms.Position % 8).Should().Be(0);
83 | ms.Position = 0;
84 | var rc = HeaderManager.Instance.ReadHeader(new FormattedReader(new FileIO(ms)));
85 | rc.Should().Not.Be.Null();
86 | rc.ItemAreaStart.Should().Be.GreaterThan(32);
87 | rc.ItemAreaEnd.Should().Be(0);
88 | rc.SectionCount.Should().Be(1);
89 | ms.Position.Should().Be(ms.Length);
90 | ms.Position.Should().Be(rc.ItemAreaStart);
91 | (ms.Position % 8).Should().Be(0);
92 | }
93 |
94 | [TestMethod]
95 | public void SignatureError()
96 | {
97 | var ms = new MemoryStream();
98 | var bw = new BinaryWriter(ms);
99 | bw.Write(123L);
100 | ms.Position = 0;
101 |
102 | Executing.This(() => HeaderManager.Instance.ReadHeader(new FormattedReader(new FileIO(ms)))).Should().Throw()
103 | .Exception.Message.Should().Contain("Expected Signature not found");
104 | }
105 |
106 | [TestMethod]
107 | public void NextSectionOffsetWrong()
108 | {
109 | var ms = new MemoryStream();
110 | var bw = new BinaryWriter(ms);
111 | bw.Write(0x0d0e0a0402080500);
112 | bw.Write(32L);
113 | bw.Write(0L);
114 | bw.Write(1L); // 1 section
115 | bw.Write(0x80);
116 | bw.Write(11111);
117 | ms.Position = 0;
118 |
119 | Executing.This(() => HeaderManager.Instance.ReadHeader(new FormattedReader(new FileIO(ms)))).Should().Throw()
120 | .Exception.Message.Should().Contain("NextSectionOffset of section");
121 | }
122 |
123 | [TestMethod]
124 | public void BadSection()
125 | {
126 | var badSectionFormatter = new Mock(MockBehavior.Strict);
127 | badSectionFormatter.Setup(sf => sf.Id).Returns(0x1000);
128 | badSectionFormatter.Setup(sf => sf.Read(It.IsAny())).Callback((ReadContext rc) => rc.Reader.SkipBytes(16));
129 | HeaderManager hm = new HeaderManager();
130 | hm.AddSectionFormatter(badSectionFormatter.Object);
131 |
132 | var ms = new MemoryStream();
133 | var bw = new BinaryWriter(ms);
134 | bw.Write(0x0d0e0a0402080500);
135 | bw.Write(200L);
136 | bw.Write(0L);
137 | bw.Write(1L); // 1 section
138 | bw.Write(badSectionFormatter.Object.Id);
139 | bw.Write(2);
140 |
141 | 20.Times(() => bw.Write(0L));
142 |
143 | ms.Position = 0;
144 |
145 | Executing.This(() => hm.ReadHeader(new FormattedReader(new FileIO(ms)))).Should().Throw()
146 | .Exception.Message.Should().Contain("Section read too many bytes");
147 | }
148 |
149 | [TestMethod]
150 | public void GeneralExceptionWhileReadingHeader()
151 | {
152 | var stream = new Mock(MockBehavior.Strict);
153 | stream.Setup(s => s.CanRead).Returns(true);
154 | stream.Setup(s => s.Read(It.IsAny(), It.IsAny(), It.IsAny())).Throws(new Exception("testException"));
155 |
156 | Executing.This(() => HeaderManager.Instance.ReadHeader(new FormattedReader(new FileIO(stream.Object)))).Should().Throw()
157 | .Exception.Message.Should().Contain("Error reading TeaFile Header: testException");
158 | }
159 | }
160 | }
161 |
--------------------------------------------------------------------------------
/TeaFiles.Test/Header/Sections/ContentSectionFormatterTest.cs:
--------------------------------------------------------------------------------
1 | // copyright discretelogics 2012. released under the gpl v3. see license.txt for details.
2 | using System;
3 | using System.Globalization;
4 | using System.IO;
5 | using System.Threading;
6 | using Microsoft.VisualStudio.TestTools.UnitTesting;
7 | using Moq;
8 | using SharpTestsEx;
9 | using TeaTime.IO;
10 |
11 | namespace TeaTime.Header.Sections
12 | {
13 | [TestClass]
14 | public class ContentSectionFormatterTest
15 | {
16 | [TestInitialize]
17 | public void Init()
18 | {
19 | // Ensure english error messages on non english systems.
20 | Thread.CurrentThread.CurrentUICulture = new CultureInfo("en-US");
21 | }
22 |
23 | [TestMethod]
24 | public void ExoticCoverageTest()
25 | {
26 | ISectionFormatter f = new ContentSectionFormatter();
27 | Executing.This(() => f.Write(null)).Should().Throw();
28 | Executing.This(() => f.Read(null)).Should().Throw();
29 | f.Id.Should().Be(0x80);
30 | }
31 |
32 | [TestMethod]
33 | public void ContentSectionFormatterEmptyDescription()
34 | {
35 | var fw = new Mock(MockBehavior.Strict);
36 | var wc = new WriteContext(fw.Object);
37 | ISectionFormatter f = new ContentSectionFormatter();
38 | f.Write(wc);
39 | // due to the strict behavior of the fw mock, this test succeeds only if no method of fw was called.
40 | }
41 |
42 | [TestMethod]
43 | public void ContentSectionFormatterDescriptionSetButNoContentDescription()
44 | {
45 | var fw = new Mock(MockBehavior.Strict);
46 | var wc = new WriteContext(fw.Object);
47 | wc.Description = new TeaFileDescription();
48 | ISectionFormatter f = new ContentSectionFormatter();
49 | f.Write(wc);
50 | // due to the strict behavior of the fw mock, this test succeeds only if no method of fw was called.
51 | }
52 |
53 | [TestMethod]
54 | public void ContentSectionFormatterRoundTrip()
55 | {
56 | const string testValue = "Météo pour Paris, France. @€";
57 |
58 | var ms = new MemoryStream();
59 | var fio = new FileIO(ms);
60 | var fw = new FormattedWriter(fio);
61 | var wc = new WriteContext(fw);
62 | wc.Description = new TeaFileDescription();
63 | wc.Description.ContentDescription = testValue;
64 | ISectionFormatter f = new ContentSectionFormatter();
65 | f.Write(wc);
66 | ms.Position = 0;
67 | var fr = new FormattedReader(fio);
68 | var rc = new ReadContext(fr);
69 | f.Read(rc);
70 | rc.Description.Should().Not.Be.Null();
71 | rc.Description.ContentDescription.Should().Be(testValue);
72 | }
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/TeaFiles.Test/Header/Sections/ItemSectionFormatterTest.cs:
--------------------------------------------------------------------------------
1 | // copyright discretelogics 2012. released under the gpl v3. see license.txt for details.
2 | using System.Globalization;
3 | using System.IO;
4 | using System.Linq;
5 | using System.Threading;
6 | using Microsoft.VisualStudio.TestTools.UnitTesting;
7 | using SharpTestsEx;
8 | using TeaTime.IO;
9 |
10 | namespace TeaTime.Header.Sections
11 | {
12 | [TestClass]
13 | public class ItemSectionFormatterTest
14 | {
15 | [TestInitialize]
16 | public void Init()
17 | {
18 | // Ensure english error messages on non english systems.
19 | Thread.CurrentThread.CurrentUICulture = new CultureInfo("en-US");
20 | }
21 |
22 | [TestMethod]
23 | public void ExoticCoverage()
24 | {
25 | ISectionFormatter f = new ItemSectionFormatter();
26 | f.Id.Should().Be(0x0a);
27 | }
28 |
29 | public struct OHLCV
30 | {
31 | public double Open;
32 | public double High;
33 | public double Low;
34 | public double Close;
35 | public long Volume;
36 | }
37 |
38 | [TestMethod]
39 | public void ItemSectionRoundTrip()
40 | {
41 | var ms = new MemoryStream();
42 | var fio = new FileIO(ms);
43 | var fw = new FormattedWriter(fio);
44 | var wc = new WriteContext(fw);
45 | wc.Description = new TeaFileDescription();
46 | var writeID =
47 | wc.Description.ItemDescription = ItemDescription.FromAnalysis>();
48 | ISectionFormatter f = new ItemSectionFormatter();
49 | f.Write(wc);
50 |
51 | ms.Position = 0;
52 |
53 | var fr = new FormattedReader(fio);
54 | var rc = new ReadContext(fr);
55 | rc.Description.Should().Not.Be.Null();
56 | f.Read(rc);
57 | rc.Description.Should().Not.Be.Null();
58 | var id = rc.Description.ItemDescription;
59 |
60 | id.ItemTypeName.Should().Be(typeof (Event).GetLanguageName());
61 | id.ItemSize.Should().Be(wc.Description.ItemDescription.ItemSize);
62 | id.Fields.Select(ff => ff.Name).Should().Have.SameValuesAs("Time", "Open", "High", "Low", "Close", "Volume");
63 | id.Fields.Select(ff => ff.Index).Should().Have.SameValuesAs(0, 1, 2, 3, 4, 5);
64 | id.Fields.Select(ff => ff.FieldType).Should().Have.SameValuesAs(FieldType.Int64, FieldType.Double, FieldType.Double, FieldType.Double, FieldType.Double);
65 | id.Fields.Select(ff => ff.Offset).Should().Have.SameValuesAs(writeID.Fields.Select(ff => ff.Offset));
66 |
67 | ms.Position.Should().Be(ms.Length); // very important, all bytes must have been read
68 | }
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/TeaFiles.Test/Header/Sections/NameValueSectionFormatterTest.cs:
--------------------------------------------------------------------------------
1 | // copyright discretelogics 2012. released under the gpl v3. see license.txt for details.
2 | using System;
3 | using System.Globalization;
4 | using System.IO;
5 | using System.Linq;
6 | using System.Threading;
7 | using Microsoft.VisualStudio.TestTools.UnitTesting;
8 | using Moq;
9 | using SharpTestsEx;
10 | using TeaTime.IO;
11 |
12 | namespace TeaTime.Header.Sections
13 | {
14 | [TestClass]
15 | public class NameValueSectionFormatterTest
16 | {
17 | [TestInitialize]
18 | public void Init()
19 | {
20 | // Ensure english error messages on non english systems.
21 | Thread.CurrentThread.CurrentUICulture = new CultureInfo("en-US");
22 | }
23 |
24 | [TestMethod]
25 | public void ExoticCoverageTest()
26 | {
27 | ISectionFormatter f = new NameValueSectionFormatter();
28 | Executing.This(() => f.Write(null)).Should().Throw();
29 | Executing.This(() => f.Read(null)).Should().Throw();
30 | f.Id.Should().Be(0x81);
31 | }
32 |
33 | [TestMethod]
34 | public void NoNameValueSectionTest()
35 | {
36 | var fw = new Mock(MockBehavior.Strict);
37 | var wc = new WriteContext(fw.Object);
38 |
39 | ISectionFormatter f = new NameValueSectionFormatter();
40 | f.Write(wc);
41 |
42 | wc.Description = new TeaFileDescription();
43 | f.Write(wc);
44 |
45 | wc.Description.NameValues = new NameValueCollection();
46 | f.Write(wc);
47 |
48 | // due to the strict behavior of the fw mock, this test succeeds only if no method of fw was called.
49 | }
50 |
51 | [TestMethod]
52 | public void NameValueSectionIOTest()
53 | {
54 | var fw = new Mock(MockBehavior.Strict);
55 | fw.Setup(w => w.WriteInt32(1));
56 | fw.Setup(w => w.WriteNameValue(It.Is(nv => nv.Name == "someName")));
57 | var wc = new WriteContext(fw.Object);
58 |
59 | ISectionFormatter f = new NameValueSectionFormatter();
60 | wc.Description = new TeaFileDescription();
61 | wc.Description.NameValues = new NameValueCollection();
62 | wc.Description.NameValues.Add(new NameValue("someName", 1.23));
63 | f.Write(wc);
64 |
65 | fw.Verify();
66 | }
67 |
68 | [TestMethod]
69 | public void NameValueSectionRoundTrip1EntryTest()
70 | {
71 | var ms = new MemoryStream();
72 | var fio = new FileIO(ms);
73 | var fw = new FormattedWriter(fio);
74 | var wc = new WriteContext(fw);
75 |
76 | ISectionFormatter f = new NameValueSectionFormatter();
77 | wc.Description = new TeaFileDescription();
78 | wc.Description.NameValues = new NameValueCollection();
79 | wc.Description.NameValues.Add(new NameValue("someName", 1.23));
80 | f.Write(wc);
81 |
82 | ms.Position = 0;
83 |
84 | var fr = new FormattedReader(fio);
85 | var rc = new ReadContext(fr);
86 | f.Read(rc);
87 |
88 | rc.Description.Should().Not.Be.Null();
89 | rc.Description.NameValues.Should().Not.Be.Null();
90 | rc.Description.NameValues.Should().Have.Count.EqualTo(1);
91 | rc.Description.NameValues.First().Name.Should().Be("someName");
92 | rc.Description.NameValues.First().GetValue().Should().Be(1.23);
93 | }
94 |
95 | [TestMethod]
96 | public void NameValueSectionRoundTrip3EntriesTest()
97 | {
98 | var ms = new MemoryStream();
99 | var fio = new FileIO(ms);
100 | var fw = new FormattedWriter(fio);
101 | var wc = new WriteContext(fw);
102 |
103 | ISectionFormatter f = new NameValueSectionFormatter();
104 | wc.Description = new TeaFileDescription();
105 | wc.Description.NameValues = new NameValueCollection();
106 | wc.Description.NameValues.Add(new NameValue("someName", 1.23));
107 | wc.Description.NameValues.Add(new NameValue("someName2", "second value"));
108 | wc.Description.NameValues.Add(new NameValue("someName3", 333));
109 | f.Write(wc);
110 |
111 | ms.Position = 0;
112 |
113 | var fr = new FormattedReader(fio);
114 | var rc = new ReadContext(fr);
115 | f.Read(rc);
116 |
117 | rc.Description.Should().Not.Be.Null();
118 | rc.Description.NameValues.Should().Not.Be.Null();
119 | rc.Description.NameValues.Should().Have.Count.EqualTo(3);
120 | rc.Description.NameValues.Select(nv => nv.Name).Should().Have.SameSequenceAs("someName", "someName2", "someName3");
121 | rc.Description.NameValues.Select(nv => nv.GetValue