public void TestLoopStream() { StreamSink <int> sa = Stream.CreateSink <int>(); (StreamLoop <int> sb, Stream <int> sb2, Stream <int> sc) = Transaction.Run(() => { StreamLoop <int> sbLocal = Stream.CreateLoop <int>(); Stream <int> scLocal = sa.Map(x => x % 10).Merge(sbLocal, (x, y) => x * y); Stream <int> sbOut = sa.Map(x => x / 10).Filter(x => x != 0); sbLocal.Loop(sbOut); return(sbLocal, sbOut, scLocal); }); List <int> @out = new List <int>(); List <int> out2 = new List <int>(); List <int> out3 = new List <int>(); IListener l = sb.Listen(@out.Add); IListener l2 = sb2.Listen(out2.Add); IListener l3 = sc.Listen(out3.Add); sa.Send(2); sa.Send(52); l3.Unlisten(); l2.Unlisten(); l.Unlisten(); CollectionAssert.AreEqual(new[] { 5 }, @out.ToArray()); CollectionAssert.AreEqual(new[] { 5 }, out2.ToArray()); CollectionAssert.AreEqual(new[] { 2, 10 }, out3.ToArray()); }
public void TestSwitchS() { StreamSink <Ss> sss = new StreamSink <Ss>(); // Split each field out of SB so we can update multiple behaviors in a // single transaction. Stream <char> sa = sss.Map(s => s.A); Stream <char> sb = sss.Map(s => s.B); Cell <Stream <char> > csw = sss.Map(s => s.Sw).FilterMaybe().Hold(sa); Stream <char> so = csw.SwitchS(); List <char> @out = new List <char>(); using (so.Listen(@out.Add)) { sss.Send(new Ss('A', 'a', Maybe.Nothing <Stream <char> >())); sss.Send(new Ss('B', 'b', Maybe.Nothing <Stream <char> >())); sss.Send(new Ss('C', 'c', Maybe.Just(sb))); sss.Send(new Ss('D', 'd', Maybe.Nothing <Stream <char> >())); sss.Send(new Ss('E', 'e', Maybe.Just(sa))); sss.Send(new Ss('F', 'f', Maybe.Nothing <Stream <char> >())); sss.Send(new Ss('G', 'g', Maybe.Just(sb))); sss.Send(new Ss('H', 'h', Maybe.Just(sa))); sss.Send(new Ss('I', 'i', Maybe.Just(sa))); } CollectionAssert.AreEqual(new[] { 'A', 'B', 'C', 'd', 'e', 'F', 'G', 'h', 'I' }, @out); }
public void TestSwitchC() { StreamSink <Sc> ssc = Stream.CreateSink <Sc>(); // Split each field out of SB so we can update multiple behaviors in a // single transaction. DiscreteCell <char> ca = ssc.Map(s => s.A).FilterMaybe().Hold('A'); DiscreteCell <char> cb = ssc.Map(s => s.B).FilterMaybe().Hold('a'); DiscreteCell <DiscreteCell <char> > csw = ssc.Map(s => s.Sw).FilterMaybe().Hold(ca); DiscreteCell <char> co = csw.SwitchC(); List <char> @out = new List <char>(); IListener l = co.Listen(@out.Add); ssc.Send(new Sc(Maybe.Just('B'), Maybe.Just('b'), Maybe.Nothing <DiscreteCell <char> >())); ssc.Send(new Sc(Maybe.Just('C'), Maybe.Just('c'), Maybe.Just(cb))); ssc.Send(new Sc(Maybe.Just('D'), Maybe.Just('d'), Maybe.Nothing <DiscreteCell <char> >())); ssc.Send(new Sc(Maybe.Just('E'), Maybe.Just('e'), Maybe.Just(ca))); ssc.Send(new Sc(Maybe.Just('F'), Maybe.Just('f'), Maybe.Nothing <DiscreteCell <char> >())); ssc.Send(new Sc(Maybe.Nothing <char>(), Maybe.Nothing <char>(), Maybe.Just(cb))); ssc.Send(new Sc(Maybe.Nothing <char>(), Maybe.Nothing <char>(), Maybe.Just(ca))); ssc.Send(new Sc(Maybe.Just('G'), Maybe.Just('g'), Maybe.Just(cb))); ssc.Send(new Sc(Maybe.Just('H'), Maybe.Just('h'), Maybe.Just(ca))); ssc.Send(new Sc(Maybe.Just('I'), Maybe.Just('i'), Maybe.Just(ca))); l.Unlisten(); CollectionAssert.AreEqual(new[] { 'A', 'B', 'c', 'd', 'E', 'F', 'f', 'F', 'g', 'H', 'I' }, @out); }
private static void Main(string[] args) { StreamSink <string> ssInput = new StreamSink <string>(); Stream <IReadOnlyList <string> > sOutput = ssInput.Map(GetOutput); Cell <bool> cExit = ssInput.Map(v => cGoodbye.Any(g => v == g)).Hold(false); using (sOutput.Listen( outputLines => { foreach (string outputLine in outputLines) { Wl(outputLine); } })) { while (!cExit.Sample()) { W("You: "); ssInput.Send(Console.ReadLine()); } } Wl(string.Empty); Wl("Press enter to exit..."); Console.ReadLine(); }
public void TestSwitchC() { StreamSink <Sc> esb = new StreamSink <Sc>(); // Split each field out of SB so we can update multiple behaviors in a // single transaction. Cell <char> ba = esb.Map(s => s.A).FilterMaybe().Hold('A'); Cell <char> bb = esb.Map(s => s.B).FilterMaybe().Hold('a'); Cell <Cell <char> > bsw = esb.Map(s => s.Sw).FilterMaybe().Hold(ba); Cell <char> bo = bsw.SwitchC(); List <char> @out = new List <char>(); using (bo.Listen(@out.Add)) { esb.Send(new Sc(Maybe.Just('B'), Maybe.Just('b'), Maybe.Nothing <Cell <char> >())); esb.Send(new Sc(Maybe.Just('C'), Maybe.Just('c'), Maybe.Just(bb))); esb.Send(new Sc(Maybe.Just('D'), Maybe.Just('d'), Maybe.Nothing <Cell <char> >())); esb.Send(new Sc(Maybe.Just('E'), Maybe.Just('e'), Maybe.Just(ba))); esb.Send(new Sc(Maybe.Just('F'), Maybe.Just('f'), Maybe.Nothing <Cell <char> >())); esb.Send(new Sc(Maybe.Nothing <char>(), Maybe.Nothing <char>(), Maybe.Just(bb))); esb.Send(new Sc(Maybe.Nothing <char>(), Maybe.Nothing <char>(), Maybe.Just(ba))); esb.Send(new Sc(Maybe.Just('G'), Maybe.Just('g'), Maybe.Just(bb))); esb.Send(new Sc(Maybe.Just('H'), Maybe.Just('h'), Maybe.Just(ba))); esb.Send(new Sc(Maybe.Just('I'), Maybe.Just('i'), Maybe.Just(ba))); } CollectionAssert.AreEqual(new[] { 'A', 'B', 'c', 'd', 'E', 'F', 'f', 'F', 'g', 'H', 'I' }, @out); }
public async Task NestedRunConstruct() { List <int> @out = new List <int>(); StreamSink <int> sink = Stream.CreateSink <int>(); Task <IListener> t = Task.Run(() => Transaction.Run(() => { Thread.Sleep(500); sink.Send(4); Stream <int> s = Transaction.Run(() => sink.Map(v => v * 2)); IListener l2 = s.Listen(@out.Add); Thread.Sleep(500); return(l2); })); await Task.Delay(250); sink.Send(5); await Task.Delay(500); sink.Send(6); IListener l = await t; sink.Send(7); l.Unlisten(); sink.Send(8); CollectionAssert.AreEqual(new[] { 8, 12, 14 }, @out); }
public void TestMapMemory() { int? beforeListenerCount = null; int? duringListenerCount = null; int? afterListenerCount = null; StreamSink<int> s = new StreamSink<int>(); Stream<string> m = s.Map(x => (x + 2).ToString()); List<string> @out = new List<string>(); dotMemory.Check(memory => beforeListenerCount = memory.GetObjects(where => where.Interface.Is<IListener>()).ObjectsCount); ((Action)(() => { using (m.Listen(@out.Add)) { dotMemory.Check(memory => duringListenerCount = memory.GetObjects(where => where.Interface.Is<IListener>()).ObjectsCount); s.Send(5); s.Send(3); } CollectionAssert.AreEqual(new[] { "7", "5" }, @out); }))(); dotMemory.Check(memory => afterListenerCount = memory.GetObjects(where => where.Interface.Is<IListener>()).ObjectsCount); Assert.IsNotNull(beforeListenerCount); Assert.IsNotNull(duringListenerCount); Assert.IsNotNull(afterListenerCount); Assert.AreEqual(beforeListenerCount, afterListenerCount, "Before == After"); Assert.IsTrue(duringListenerCount > beforeListenerCount, "During > Before"); }
public void TestMapMemory() { int?beforeListenerCount = null; int?duringListenerCount = null; int?afterListenerCount = null; StreamSink <int> s = Stream.CreateSink <int>(); Stream <string> m = s.Map(x => (x + 2).ToString()); List <string> @out = new List <string>(); dotMemory.Check(memory => beforeListenerCount = memory.GetObjects(where => where.Interface.Is <IListener>()).ObjectsCount); ((Action)(() => { IListener l = m.Listen(@out.Add); dotMemory.Check(memory => duringListenerCount = memory.GetObjects(where => where.Interface.Is <IListener>()).ObjectsCount); s.Send(5); s.Send(3); l.Unlisten(); CollectionAssert.AreEqual(new[] { "7", "5" }, @out); }))(); dotMemory.Check(memory => afterListenerCount = memory.GetObjects(where => where.Interface.Is <IListener>()).ObjectsCount); Assert.IsNotNull(beforeListenerCount); Assert.IsNotNull(duringListenerCount); Assert.IsNotNull(afterListenerCount); Assert.AreEqual(beforeListenerCount, afterListenerCount, "Before == After"); Assert.IsTrue(duringListenerCount > beforeListenerCount, "During > Before"); }
public void TestStreamSendInMapThrowsException() { InvalidOperationException actual = null; StreamSink <int> s = Stream.CreateSink <int>(); StreamSink <int> s2 = Stream.CreateSink <int>(); using (s.Map( v => { s2.Send(v); return(Unit.Value); }) .Listen(_ => { })) { try { s.Send(5); } catch (InvalidOperationException e) { actual = e; } } Assert.IsNotNull(actual); Assert.AreEqual("Send may not be called inside a Sodium callback.", actual.Message); }
public void Issue151_PoolDoubleSubtraction_Fixed() { CellSink <int> threshold = new CellSink <int>(10); StreamSink <int> addPoolSink = new StreamSink <int>(); (Stream <int> input, Cell <int> pool) = Transaction.Run(() => { StreamLoop <int> submitPooledAmount = new StreamLoop <int>(); // Ways that the pool is modified. Stream <Func <int, int> > poolAddByInput = addPoolSink.Map <Func <int, int> >(i => x => x + i); Stream <Func <int, int> > poolRemoveByUsage = Operational.Defer(submitPooledAmount.Map <Func <int, int> >(i => x => x - i)); // The current level of the pool Cell <int> poolLocal = poolAddByInput .Merge(poolRemoveByUsage, (f, g) => x => g(f(x))) .Accum(0, (f, x) => f(x)); // The current input changes combined with the pool as a stream Stream <int> inputByAdded = poolAddByInput .Snapshot( poolLocal, threshold, (f, x, t) => f(x) >= t ? Maybe.Some(f(x)) : Maybe.None) .FilterMaybe(); // Simple rising edge on pool threshold satisfaction. Stream <int> inputBySatisfaction = poolLocal.Updates .Snapshot( poolLocal, threshold, (neu, alt, t) => neu >= t && alt < t ? Maybe.Some(neu) : Maybe.None) .FilterMaybe(); submitPooledAmount.Loop(inputByAdded.Merge(inputBySatisfaction, Math.Max)); return(submitPooledAmount, poolLocal); }); List <int> submissions = new List <int>(); using (input.Listen(submissions.Add)) { // Add amount which can be immediately used based on threshold. // Pool should remain zero after the transaction is complete. addPoolSink.Send(10); } Assert.AreEqual(1, submissions.Count); Assert.AreEqual(10, submissions[0]); Assert.AreEqual(0, pool.Sample()); }
public void Issue151_PoolDoubleSubtraction_Broken() { Exception actual = null; try { CellSink <int> threshold = new CellSink <int>(10); StreamSink <int> addPoolSink = new StreamSink <int>(); Transaction.Run(() => { StreamLoop <int> submitPooledAmount = new StreamLoop <int>(); // Ways that the pool is modified. Stream <Func <int, int> > poolAddByInput = addPoolSink.Map <Func <int, int> >(i => x => x + i); Stream <Func <int, int> > poolRemoveByUsage = submitPooledAmount.Map <Func <int, int> >(i => x => x - i); // The current level of the pool Cell <int> poolLocal = poolAddByInput .Merge(poolRemoveByUsage, (f, g) => x => g(f(x))) .Accum(0, (f, x) => f(x)); // The current input changes combined with the pool as a stream Stream <int> inputByAdded = poolAddByInput .Snapshot( poolLocal, threshold, (f, x, t) => f(x) >= t ? Maybe.Some(f(x)) : Maybe.None) .FilterMaybe(); // Simple rising edge on pool threshold satisfaction. Stream <int> inputBySatisfaction = poolLocal.Updates .Snapshot( poolLocal, threshold, (neu, alt, t) => neu >= t && alt < t ? Maybe.Some(neu) : Maybe.None) .FilterMaybe(); submitPooledAmount.Loop(inputByAdded.Merge(inputBySatisfaction, Math.Max)); return(submitPooledAmount, poolLocal); }); } catch (Exception e) { actual = e; } Assert.IsNotNull(actual); Assert.AreEqual("A dependency cycle was detected.", actual.Message); }
public void Run() { StreamSink <int> sX = Stream.CreateSink <int>(); Stream <int> sXPlus1 = sX.Map(x => x + 1); IListener l = sXPlus1.Listen(Console.WriteLine); sX.Send(1); sX.Send(2); sX.Send(3); l.Unlisten(); }
public void TestLoopStream() { StreamSink <int> sa = new StreamSink <int>(); Stream <int> sc = Transaction.Run(() => { StreamLoop <int> sb = new StreamLoop <int>(); Stream <int> scLocal = sa.Map(x => x % 10).Merge(sb, (x, y) => x * y); Stream <int> sbOut = sa.Map(x => x / 10).Filter(x => x != 0); sb.Loop(sbOut); return(scLocal); }); List <int> @out = new List <int>(); using (sc.Listen(@out.Add)) { sa.Send(2); sa.Send(52); } CollectionAssert.AreEqual(new[] { 2, 10 }, @out.ToArray()); }
public void Run() { StreamSink <int> sX = new StreamSink <int>(); Stream <int> sXPlus1 = sX.Map(x => x + 1); using (sXPlus1.Listen(Console.WriteLine)) { sX.Send(1); sX.Send(2); sX.Send(3); } }
public void TestMergeSimultaneous() { StreamSink <int> s = Stream.CreateSink <int>(); Stream <int> s2 = s.Map(x => 2 * x); List <int> @out = new List <int>(); IListener l = s.Merge(s2, (x, y) => x + y).Listen(@out.Add); s.Send(7); s.Send(9); l.Unlisten(); CollectionAssert.AreEqual(new[] { 21, 27 }, @out); }
public void TestOrElseSimultaneous2() { StreamSink <int> s = Stream.CreateSink <int>(); Stream <int> s2 = s.Map(x => 2 * x); List <int> @out = new List <int>(); IListener l = s.OrElse(s2).Listen(@out.Add); s.Send(7); s.Send(9); l.Unlisten(); CollectionAssert.AreEqual(new[] { 7, 9 }, @out); }
public void TestMap() { StreamSink <int> s = Stream.CreateSink <int>(); Stream <string> m = s.Map(x => (x + 2).ToString()); List <string> @out = new List <string>(); IListener l = m.Listen(@out.Add); s.Send(5); s.Send(3); l.Unlisten(); CollectionAssert.AreEqual(new[] { "7", "5" }, @out); }
public void TestOrElseLeftBias() { StreamSink <int> s = Stream.CreateSink <int>(); Stream <int> s2 = s.Map(x => 2 * x); List <int> @out = new List <int>(); IListener l = s2.OrElse(s).Listen(@out.Add); s.Send(7); s.Send(9); l.Unlisten(); CollectionAssert.AreEqual(new[] { 14, 18 }, @out); }
public void TestUnlisten() { int?listenerCount = null; int?listenerCount2 = null; int?listenerCount3 = null; int?listenerCount4 = null; int?beforeListenerCount = null; int?duringListenerCount = null; int?duringStreamCount = null; int?afterListenerCount = null; ((Action)(() => { StreamSink <int> s = Stream.CreateSink <int>(); dotMemory.Check(memory => listenerCount = memory.GetObjects(where => where.Interface.Is <IListener>()).ObjectsCount); dotMemory.Check(memory => beforeListenerCount = memory.GetObjects(where => where.Type.Is <Stream <string> >()).ObjectsCount); Stream <string> m = s.Map(x => (x + 2).ToString()); List <string> @out = new List <string>(); ((Action)(() => { IListener listener = m.Listen(@out.Add); listener.Unlisten(); dotMemory.Check(memory => listenerCount2 = memory.GetObjects(where => where.Interface.Is <IListener>()).ObjectsCount); dotMemory.Check(memory => duringListenerCount = memory.GetObjects(where => where.Type.Is <Stream <string> >()).ObjectsCount); }))(); dotMemory.Check(memory => listenerCount3 = memory.GetObjects(where => where.Interface.Is <IListener>()).ObjectsCount); dotMemory.Check(memory => duringStreamCount = memory.GetObjects(where => where.Type.Is <Stream <string> >()).ObjectsCount); }))(); dotMemory.Check(memory => listenerCount4 = memory.GetObjects(where => where.Interface.Is <IListener>()).ObjectsCount); dotMemory.Check(memory => afterListenerCount = memory.GetObjects(where => where.Type.Is <Stream <string> >()).ObjectsCount); Assert.IsNotNull(beforeListenerCount); Assert.IsNotNull(listenerCount); Assert.IsNotNull(listenerCount2); Assert.IsNotNull(duringListenerCount); Assert.IsNotNull(duringStreamCount); Assert.IsNotNull(afterListenerCount); Assert.AreEqual(listenerCount, listenerCount4, "BeforeL == After2L"); Assert.IsTrue(listenerCount2 > listenerCount3, "DuringL > AfterL"); Assert.IsTrue(listenerCount2 > listenerCount, "DuringL > BeforeL"); Assert.AreEqual(beforeListenerCount, afterListenerCount, "Before == After"); Assert.AreEqual(duringListenerCount, duringStreamCount, "During == During2"); Assert.IsTrue(duringListenerCount > beforeListenerCount, "During > Before"); }
public void TestOrElseSimultaneous2() { StreamSink <int> s = new StreamSink <int>(); Stream <int> s2 = s.Map(x => 2 * x); List <int> @out = new List <int>(); using (s.OrElse(s2).Listen(@out.Add)) { s.Send(7); s.Send(9); } CollectionAssert.AreEqual(new[] { 7, 9 }, @out); }
public void TestOrElseLeftBias() { StreamSink <int> s = new StreamSink <int>(); Stream <int> s2 = s.Map(x => 2 * x); List <int> @out = new List <int>(); using (s2.OrElse(s).Listen(@out.Add)) { s.Send(7); s.Send(9); } CollectionAssert.AreEqual(new[] { 14, 18 }, @out); }
public void TestMergeSimultaneous() { StreamSink <int> s = new StreamSink <int>(); Stream <int> s2 = s.Map(x => 2 * x); List <int> @out = new List <int>(); using (s.Merge(s2, (x, y) => x + y).Listen(@out.Add)) { s.Send(7); s.Send(9); } CollectionAssert.AreEqual(new[] { 21, 27 }, @out); }
public void TestMap() { StreamSink <int> s = new StreamSink <int>(); Stream <string> m = s.Map(x => (x + 2).ToString()); List <string> @out = new List <string>(); using (m.Listen(@out.Add)) { s.Send(5); s.Send(3); } CollectionAssert.AreEqual(new[] { "7", "5" }, @out); }
public void Run() { StreamSink <int> sX = Stream.CreateSink <int>(); Stream <int> sXPlus1 = sX.Map(x => x + 1); IListener l = Transaction.Run(() => { sX.Send(1); return(sXPlus1.Listen(Console.WriteLine)); }); sX.Send(2); sX.Send(3); l.Unlisten(); }
public void Run() { StreamSink<int> sX = new StreamSink<int>(); Stream<int> sXPlus1 = sX.Map(x => x + 1); using (Transaction.Run(() => { sX.Send(1); return sXPlus1.Listen(Console.WriteLine); })) { sX.Send(2); sX.Send(3); } }
public void Run() { StreamSink <int> sX = new StreamSink <int>(); Stream <int> sXPlus1 = sX.Map(x => x + 1); using (Transaction.Run(() => { sX.Send(1); return(sXPlus1.Listen(Console.WriteLine)); })) { sX.Send(2); sX.Send(3); } }
public void TestNestedMapGarbageCollection() { int? beforeStreamCount = null; int? beforeListenerCount = null; int? duringStreamCount = null; int? duringListenerCount = null; int? afterStreamCount = null; int? afterListenerCount = null; StreamSink<int> s = new StreamSink<int>(); List<string> @out = new List<string>(); dotMemory.Check(memory => beforeStreamCount = memory.GetObjects(where => where.Type.Is<Stream<int>>()).ObjectsCount + memory.GetObjects(where => where.Type.Is<Stream<string>>()).ObjectsCount); dotMemory.Check(memory => beforeListenerCount = memory.GetObjects(where => where.Interface.Is<IListener>()).ObjectsCount); ((Action)(() => { Stream<string> m = s.Map(x => x + 2).Map(x => 2 * x).Map(x => x + 1).Map(x => x.ToString()); using (m.Listen(@out.Add)) { dotMemory.Check(memory => duringStreamCount = memory.GetObjects(where => where.Type.Is<Stream<int>>()).ObjectsCount + memory.GetObjects(where => where.Type.Is<Stream<string>>()).ObjectsCount); dotMemory.Check(memory => duringListenerCount = memory.GetObjects(where => where.Interface.Is<IListener>()).ObjectsCount); s.Send(5); s.Send(3); } CollectionAssert.AreEqual(new[] { "15", "11" }, @out); }))(); dotMemory.Check(memory => afterStreamCount = memory.GetObjects(where => where.Type.Is<Stream<int>>()).ObjectsCount + memory.GetObjects(where => where.Type.Is<Stream<string>>()).ObjectsCount); dotMemory.Check(memory => afterListenerCount = memory.GetObjects(where => where.Interface.Is<IListener>()).ObjectsCount); // although all listeners and streams have been cleand up, the nodes will not be disconnected until the stream fires next Assert.AreEqual(1, s.Node.GetListeners().Count); s.Send(1); Assert.AreEqual(0, s.Node.GetListeners().Count); Assert.IsNotNull(beforeStreamCount); Assert.IsNotNull(beforeListenerCount); Assert.IsNotNull(duringStreamCount); Assert.IsNotNull(duringListenerCount); Assert.IsNotNull(afterStreamCount); Assert.IsNotNull(afterListenerCount); Assert.AreEqual(beforeStreamCount, afterStreamCount, "Before Streams == After Streams"); Assert.AreEqual(beforeListenerCount, afterListenerCount, "Before Listeners == After Listeners"); Assert.IsTrue(duringStreamCount > beforeStreamCount, "During Streams > Before Streams"); Assert.IsTrue(duringListenerCount > beforeListenerCount, "During Listeners > Before Listeners"); }
public void TestNestedMapGarbageCollection() { int?beforeStreamCount = null; int?beforeListenerCount = null; int?duringStreamCount = null; int?duringListenerCount = null; int?afterStreamCount = null; int?afterListenerCount = null; StreamSink <int> s = new StreamSink <int>(); List <string> @out = new List <string>(); dotMemory.Check(memory => beforeStreamCount = memory.GetObjects(where => where.Type.Is <Stream <int> >()).ObjectsCount + memory.GetObjects(where => where.Type.Is <Stream <string> >()).ObjectsCount); dotMemory.Check(memory => beforeListenerCount = memory.GetObjects(where => where.Interface.Is <IListener>()).ObjectsCount); ((Action)(() => { Stream <string> m = s.Map(x => x + 2).Map(x => 2 * x).Map(x => x + 1).Map(x => x.ToString()); using (m.Listen(@out.Add)) { dotMemory.Check(memory => duringStreamCount = memory.GetObjects(where => where.Type.Is <Stream <int> >()).ObjectsCount + memory.GetObjects(where => where.Type.Is <Stream <string> >()).ObjectsCount); dotMemory.Check(memory => duringListenerCount = memory.GetObjects(where => where.Interface.Is <IListener>()).ObjectsCount); s.Send(5); s.Send(3); } CollectionAssert.AreEqual(new[] { "15", "11" }, @out); }))(); dotMemory.Check(memory => afterStreamCount = memory.GetObjects(where => where.Type.Is <Stream <int> >()).ObjectsCount + memory.GetObjects(where => where.Type.Is <Stream <string> >()).ObjectsCount); dotMemory.Check(memory => afterListenerCount = memory.GetObjects(where => where.Interface.Is <IListener>()).ObjectsCount); // although all listeners and streams have been cleand up, the nodes will not be disconnected until the stream fires next Assert.AreEqual(1, s.Node.GetListeners().Count); s.Send(1); Assert.AreEqual(0, s.Node.GetListeners().Count); Assert.IsNotNull(beforeStreamCount); Assert.IsNotNull(beforeListenerCount); Assert.IsNotNull(duringStreamCount); Assert.IsNotNull(duringListenerCount); Assert.IsNotNull(afterStreamCount); Assert.IsNotNull(afterListenerCount); Assert.AreEqual(beforeStreamCount, afterStreamCount, "Before Streams == After Streams"); Assert.AreEqual(beforeListenerCount, afterListenerCount, "Before Listeners == After Listeners"); Assert.IsTrue(duringStreamCount > beforeStreamCount, "During Streams > Before Streams"); Assert.IsTrue(duringListenerCount > beforeListenerCount, "During Listeners > Before Listeners"); }
public void TestStreamGarbageCollection() { int?beforeListenerCount = null; int?duringListenerCount = 3; int?duringListenerCount2 = 3; int?afterListenerCount = null; ((Action)(() => { IDisposable listener = null; StreamSink <int> s = new StreamSink <int>(); dotMemory.Check(memory => beforeListenerCount = memory.GetObjects(where => where.Type.Is <Stream <string> >()).ObjectsCount); ((Action)(() => { Stream <string> m = s.Map(x => (x + 2).ToString()); List <string> @out = new List <string>(); listener = m.Listen(@out.Add); dotMemory.Check(memory => duringListenerCount = memory.GetObjects(where => where.Type.Is <Stream <string> >()).ObjectsCount); }))(); dotMemory.Check(memory => duringListenerCount2 = memory.GetObjects(where => where.Type.Is <Stream <string> >()).ObjectsCount); using (listener) { } }))(); dotMemory.Check(memory => afterListenerCount = memory.GetObjects(where => where.Type.Is <Stream <string> >()).ObjectsCount); Assert.IsNotNull(beforeListenerCount); Assert.IsNotNull(duringListenerCount); Assert.IsNotNull(duringListenerCount2); Assert.IsNotNull(afterListenerCount); Assert.AreEqual(beforeListenerCount, afterListenerCount, "Before == After"); Assert.AreEqual(duringListenerCount, duringListenerCount2, "During == During2"); Assert.IsTrue(duringListenerCount > beforeListenerCount, "During > Before"); }
public void RunConstruct() { List <int> @out = new List <int>(); Tuple <StreamSink <int>, IListener> t = Transaction.RunConstruct(() => { StreamSink <int> sink = Stream.CreateSink <int>(); sink.Send(4); Stream <int> s = sink.Map(v => v * 2); IListener l = s.Listen(@out.Add); return(Tuple.Create(sink, l)); }); t.Item1.Send(5); t.Item1.Send(6); t.Item1.Send(7); t.Item2.Unlisten(); t.Item1.Send(8); CollectionAssert.AreEqual(new[] { 8, 10, 12, 14 }, @out); }
public void RunConstruct() { List <int> @out = new List <int>(); (StreamSink <int> s, IListener l) = Transaction.Run(() => { StreamSink <int> sink = Stream.CreateSink <int>(); sink.Send(4); Stream <int> sLocal = sink.Map(v => v * 2); IListener lLocal = sLocal.Listen(@out.Add); return(sink, lLocal); }); s.Send(5); s.Send(6); s.Send(7); l.Unlisten(); s.Send(8); CollectionAssert.AreEqual(new[] { 8, 10, 12, 14 }, @out); }
public void TestListenWeakWithMap() { StreamSink <int> s = Stream.CreateSink <int>(); List <int> @out = new List <int>(); ((Action)(() => { Stream <int> s2 = s.Map(v => v + 1); ((Action)(() => { // ReSharper disable once UnusedVariable IWeakListener l = s2.ListenWeak(@out.Add); s.Send(1); s.Send(2); }))(); GC.Collect(0, GCCollectionMode.Forced); ((Action)(() => { // ReSharper disable once UnusedVariable IWeakListener l = s2.ListenWeak(@out.Add); s.Send(3); s.Send(4); s.Send(5); }))(); }))(); GC.Collect(0, GCCollectionMode.Forced); s.Send(6); s.Send(7); Assert.AreEqual(5, @out.Count); }
public void TestSwitchC() { StreamSink<Sc> ssc = new StreamSink<Sc>(); // Split each field out of SB so we can update multiple behaviors in a // single transaction. Cell<char> ca = ssc.Map(s => s.A).FilterMaybe().Hold('A'); Cell<char> cb = ssc.Map(s => s.B).FilterMaybe().Hold('a'); Cell<Cell<char>> csw = ssc.Map(s => s.Sw).FilterMaybe().Hold(ca); Cell<char> co = csw.SwitchC(); List<char> @out = new List<char>(); using (co.Listen(@out.Add)) { ssc.Send(new Sc(Maybe.Just('B'), Maybe.Just('b'), Maybe.Nothing<Cell<char>>())); ssc.Send(new Sc(Maybe.Just('C'), Maybe.Just('c'), Maybe.Just(cb))); ssc.Send(new Sc(Maybe.Just('D'), Maybe.Just('d'), Maybe.Nothing<Cell<char>>())); ssc.Send(new Sc(Maybe.Just('E'), Maybe.Just('e'), Maybe.Just(ca))); ssc.Send(new Sc(Maybe.Just('F'), Maybe.Just('f'), Maybe.Nothing<Cell<char>>())); ssc.Send(new Sc(Maybe.Nothing<char>(), Maybe.Nothing<char>(), Maybe.Just(cb))); ssc.Send(new Sc(Maybe.Nothing<char>(), Maybe.Nothing<char>(), Maybe.Just(ca))); ssc.Send(new Sc(Maybe.Just('G'), Maybe.Just('g'), Maybe.Just(cb))); ssc.Send(new Sc(Maybe.Just('H'), Maybe.Just('h'), Maybe.Just(ca))); ssc.Send(new Sc(Maybe.Just('I'), Maybe.Just('i'), Maybe.Just(ca))); } CollectionAssert.AreEqual(new[] { 'A', 'B', 'c', 'd', 'E', 'F', 'f', 'F', 'g', 'H', 'I' }, @out); }
public void TestMap() { StreamSink<int> s = new StreamSink<int>(); Stream<string> m = s.Map(x => (x + 2).ToString()); List<string> @out = new List<string>(); using (m.Listen(@out.Add)) { s.Send(5); s.Send(3); } CollectionAssert.AreEqual(new[] { "7", "5" }, @out); }
public void TestMergeSimultaneous() { StreamSink<int> s = new StreamSink<int>(); Stream<int> s2 = s.Map(x => 2 * x); List<int> @out = new List<int>(); using (s.Merge(s2, (x, y) => x + y).Listen(@out.Add)) { s.Send(7); s.Send(9); } CollectionAssert.AreEqual(new[] { 21, 27 }, @out); }
public void TestOrElseLeftBias() { StreamSink<int> s = new StreamSink<int>(); Stream<int> s2 = s.Map(x => 2 * x); List<int> @out = new List<int>(); using (s2.OrElse(s).Listen(@out.Add)) { s.Send(7); s.Send(9); } CollectionAssert.AreEqual(new[] { 14, 18 }, @out); }
public void TestOrElseSimultaneous2() { StreamSink<int> s = new StreamSink<int>(); Stream<int> s2 = s.Map(x => 2 * x); List<int> @out = new List<int>(); using (s.OrElse(s2).Listen(@out.Add)) { s.Send(7); s.Send(9); } CollectionAssert.AreEqual(new[] { 7, 9 }, @out); }
public void TestStreamGarbageCollection() { int? beforeListenerCount = null; int? duringListenerCount = 3; int? duringListenerCount2 = 3; int? afterListenerCount = null; ((Action)(() => { IDisposable listener = null; StreamSink<int> s = new StreamSink<int>(); dotMemory.Check(memory => beforeListenerCount = memory.GetObjects(where => where.Type.Is<Stream<string>>()).ObjectsCount); ((Action)(() => { Stream<string> m = s.Map(x => (x + 2).ToString()); List<string> @out = new List<string>(); listener = m.Listen(@out.Add); dotMemory.Check(memory => duringListenerCount = memory.GetObjects(where => where.Type.Is<Stream<string>>()).ObjectsCount); }))(); dotMemory.Check(memory => duringListenerCount2 = memory.GetObjects(where => where.Type.Is<Stream<string>>()).ObjectsCount); using (listener) { } }))(); dotMemory.Check(memory => afterListenerCount = memory.GetObjects(where => where.Type.Is<Stream<string>>()).ObjectsCount); Assert.IsNotNull(beforeListenerCount); Assert.IsNotNull(duringListenerCount); Assert.IsNotNull(duringListenerCount2); Assert.IsNotNull(afterListenerCount); Assert.AreEqual(beforeListenerCount, afterListenerCount, "Before == After"); Assert.AreEqual(duringListenerCount, duringListenerCount2, "During == During2"); Assert.IsTrue(duringListenerCount > beforeListenerCount, "During > Before"); }
public void TestSwitchS() { StreamSink<Ss> sss = new StreamSink<Ss>(); // Split each field out of SB so we can update multiple behaviors in a // single transaction. Stream<char> sa = sss.Map(s => s.A); Stream<char> sb = sss.Map(s => s.B); Cell<Stream<char>> csw = sss.Map(s => s.Sw).FilterMaybe().Hold(sa); Stream<char> so = csw.SwitchS(); List<char> @out = new List<char>(); using (so.Listen(@out.Add)) { sss.Send(new Ss('A', 'a', Maybe.Nothing<Stream<char>>())); sss.Send(new Ss('B', 'b', Maybe.Nothing<Stream<char>>())); sss.Send(new Ss('C', 'c', Maybe.Just(sb))); sss.Send(new Ss('D', 'd', Maybe.Nothing<Stream<char>>())); sss.Send(new Ss('E', 'e', Maybe.Just(sa))); sss.Send(new Ss('F', 'f', Maybe.Nothing<Stream<char>>())); sss.Send(new Ss('G', 'g', Maybe.Just(sb))); sss.Send(new Ss('H', 'h', Maybe.Just(sa))); sss.Send(new Ss('I', 'i', Maybe.Just(sa))); } CollectionAssert.AreEqual(new[] { 'A', 'B', 'C', 'd', 'e', 'F', 'G', 'h', 'I' }, @out); }
public void TestLoopStream() { StreamSink<int> sa = new StreamSink<int>(); Stream<int> sc = Transaction.Run(() => { StreamLoop<int> sb = new StreamLoop<int>(); Stream<int> scLocal = sa.Map(x => x % 10).Merge(sb, (x, y) => x * y); Stream<int> sbOut = sa.Map(x => x / 10).Filter(x => x != 0); sb.Loop(sbOut); return scLocal; }); List<int> @out = new List<int>(); using (sc.Listen(@out.Add)) { sa.Send(2); sa.Send(52); } CollectionAssert.AreEqual(new[] { 2, 10 }, @out.ToArray()); }
public void FunctionalStreamLoopWithCaptures() { StreamSink <int> s = Stream.CreateSink <int>(); (Stream <int> result, Stream <int> s2) = Stream.Loop <int>() .WithCaptures(l => (Stream: s.Snapshot(l.Hold(0), (n, o) => n + o), Captures: s.Map(v => 2 * v))); List <int> @out = new List <int>(); List <int> out2 = new List <int>(); using (result.Listen(@out.Add)) using (s2.Listen(out2.Add)) { s.Send(1); s.Send(2); s.Send(3); } CollectionAssert.AreEqual(new[] { 1, 3, 6 }, @out); CollectionAssert.AreEqual(new[] { 2, 4, 6 }, out2); }
public void Run() { StreamSink<int> sX = new StreamSink<int>(); Stream<int> sXPlus1 = sX.Map(x => x + 1); using (sXPlus1.Listen(Console.WriteLine)) { sX.Send(1); sX.Send(2); sX.Send(3); } }