in Sources/Runtime/Test.Psi/OperatorTests.cs [1097:1243]
public void DynamicWindow()
{
// test sets of window and expected result pairs
void Test(((int, int, int) Window, int[] Expected)[] pairs, bool leftInclusive, bool rightInclusive)
{
// data is a 0..9 range, windows are start/end indexes into this + obsolete index
int[][] GetWindowedData(IEnumerable<(int Obsolete, int Start, int End)> windows)
{
// indexes mapped to originating time
DateTime ToTime(int i)
{
return DateTime.MinValue.AddMilliseconds(i * 10);
}
using (var p = Pipeline.Create())
{
var output = Generators.Sequence(p, new[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }.Select(d => (d, ToTime(d))))
.Window(
Generators.Sequence(p, windows, TimeSpan.FromMilliseconds(10)),
m => (new TimeInterval(ToTime(m.Data.Start), leftInclusive, ToTime(m.Data.End), rightInclusive), ToTime(m.Data.Obsolete)))
.Select(ms => ms.Select(m => m.Data).ToArray())
.ToObservable().ToListObservable();
p.Run();
return output.AsEnumerable().ToArray();
}
}
// get windowed data and compare with expected results
var results = GetWindowedData(pairs.Select(p => p.Window));
Assert.AreEqual(results.Length, pairs.Count());
for (var i = 0; i < results.Length; i++)
{
Assert.IsTrue(Enumerable.SequenceEqual(results[i], pairs[i].Expected));
}
}
// test growing (right) window - pairs are (obsolete, start, end) windows with expected windowed data
Test(
new[]
{
((2, 2, 4), new[] { 2, 3, 4 }), // 2..4 growing to right
((2, 2, 5), new[] { 2, 3, 4, 5 }), // 2..5
((2, 2, 6), new[] { 2, 3, 4, 5, 6 }), // 2..6
},
true,
true);
// test left inclusivity
Test(
new[]
{
((2, 2, 4), new[] { 3, 4 }),
((2, 2, 5), new[] { 3, 4, 5 }),
((2, 2, 6), new[] { 3, 4, 5, 6 }),
},
false /* not including left */,
true);
// test right inclusivity
Test(
new[]
{
((2, 2, 4), new[] { 2, 3 }),
((2, 2, 5), new[] { 2, 3, 4 }),
((2, 2, 6), new[] { 2, 3, 4, 5 }),
},
true,
false /* not including right */);
// test left & right inclusivity
Test(
new[]
{
((2, 2, 4), new[] { 3 }),
((2, 2, 5), new[] { 3, 4 }),
((2, 2, 6), new[] { 3, 4, 5 }),
},
false /* not including left */,
false /* not including right */);
// test left-most window
Test(new[] { ((0, 0, 2), new[] { 0, 1, 2 }), }, true, true);
// test right-most window
Test(new[] { ((7, 7, 9), new[] { 7, 8, 9 }), }, true, true);
// test beyond right-most window
Test(new[] { ((7, 7, 100), new[] { 7, 8, 9 }), }, true, true);
// test sliding window
Test(
new[]
{
((2, 2, 4), new[] { 2, 3, 4 }), // 2..4 sliding to right
((3, 3, 5), new[] { 3, 4, 5 }), // 3..6
((4, 4, 6), new[] { 4, 5, 6 }), // 4..7
},
true,
true);
// test growing (left) window
Test(
new[]
{
((1, 3, 5), new[] { 3, 4, 5 }), // 3..5 growing to left
((1, 2, 5), new[] { 2, 3, 4, 5 }), // 2..4
((1, 1, 5), new[] { 1, 2, 3, 4, 5 }), // 1..5
},
true,
true);
// invalid if obsolete time moves backward!
try
{
Test(
new[]
{
((3, 3, 5), new[] { 3, 4, 5 }), // 3..5 growing to left
((2, 3, 5), new[] { 3, 4, 5 }), // 3..4 boom! (2 earlier than previous [3] obsolete)
},
true,
true);
Assert.Fail("Expected exception due to obsolete time backtracking");
}
catch (Exception ex)
{
Assert.AreEqual(ex.InnerException.Message, "Dynamic window with obsolete time prior to previous window.");
}
// invalid if window requests are before previous obsolete time
try
{
Test(
new[]
{
((3, 3, 5), new[] { 3, 4, 5 }), // 3..5 growing to left
((3, 2, 5), new[] { 1, 3, 4, 5 }), // 2..5 boom! (2 has already been obsoleted)
},
true,
true);
Assert.Fail("Expected exception due to window request into obsoleted inputs");
}
catch (Exception ex)
{
Assert.AreEqual(ex.InnerException.Message, "Dynamic window must not extend before previous obsolete time.");
}
}