public void CaptureReader_Can_Read_Back_A_Stream_That_Was_Written_By_A_CaptureWriter()
        {
            var writeOperations = 100;
            var ms = new ConcurrentStream(new MemoryStream());

            var sat = new Dictionary<Guid, short>();
            sat.Add(Guid.NewGuid(), 24);
            sat.Add(Guid.NewGuid(), 25);
            sat.Add(Guid.NewGuid(), 26);

            var stateResolver = new Mock<IStateResolver>();
            stateResolver.SetupGet(s => s.AllocationTable).Returns(sat);
            stateResolver.Setup(s => s.IsAllocated(It.IsAny<Guid>())).Returns<Guid>(g => sat.ContainsKey(g));
            stateResolver.Setup(s => s.GetAllocatedId(It.IsAny<Guid>())).Returns<Guid>(g => sat[g]);

            //write operations
            var captureWriter = new CaptureWriter(ms, stateResolver.Object);

            for (int i = 0; i < writeOperations; i++)
            {
                var timestamp = DateTime.UtcNow;
                var randomData = new byte[1024];
                new Random().NextBytes(randomData);

                var randomSat = (short)new Random().Next(24, 26);

                var captureState = new Mock<ICaptureState>();
                captureState.Setup(c => c.Data).Returns(randomData);
                captureState.Setup(c => c.Guid).Returns(sat.Where(f => f.Value == randomSat).First().Key);
                captureState.Setup(c => c.Timestamp).Returns(timestamp);

                captureWriter.Write(captureState.Object);
            }

            //rewind the stream to the beginning
            ms.Position = 0;

            //read operations
            var readStateResolver = new StateResolver();
            readStateResolver.Add(new SimpleStateController { Guid = sat.Where(f => f.Value == 24).First().Key });
            readStateResolver.Add(new SimpleStateController { Guid = sat.Where(f => f.Value == 25).First().Key });
            readStateResolver.Add(new SimpleStateController { Guid = sat.Where(f => f.Value == 26).First().Key });

            var captureReader = new CaptureReader(ms, readStateResolver);

            while (captureReader.Position < captureReader.Count)
            {
                captureReader.Read();
            }
        }
Beispiel #2
0
        /// <summary>
        /// Creates a new instance of the CaptureStream with the specified base stream and mode
        /// </summary>
        /// <param name="stream"></param>
        public CaptureStream(IStream baseStream, System.IO.FileAccess fileAccess, IStateResolver stateResolver)
        {
            switch (fileAccess)
            {
                case System.IO.FileAccess.Read:
                    {
                        _CaptureReader = new CaptureReader(baseStream, stateResolver);

                        this.Timestamp = _CaptureReader.Timestamp;
                        break;
                    }
                case System.IO.FileAccess.Write:
                    {
                        _CaptureWriter = new CaptureWriter(baseStream, stateResolver);

                        this.Timestamp = _CaptureWriter.Timestamp;
                        break;
                    }
                default:
                    {
                        var streamPosition = baseStream.Position;

                        //important to create writer first, it will create the header the reader expects (if required)
                        _CaptureWriter = new CaptureWriter(baseStream, stateResolver);

                        //put the position back to the original position
                        baseStream.Position = streamPosition;

                        //reader now has a valid continuum file to play
                        _CaptureReader = new CaptureReader(baseStream, stateResolver);

                        this.Timestamp = _CaptureWriter.Timestamp;

                        break;
                    }
            }

            this.StateResolver = stateResolver;

            //store the read/write pointers
            _ReadPointer = baseStream.Position;
            _WritePointer = baseStream.Position;
            _Lock = new object();
        }
        public void CaptureStream_Supports_Reading_A_File_For_Playback_Prior_To_The_Entire_File_Becoming_Available()
        {
            //base bytes to feed into the stream at random
            var bytes = VastPark.FrameworkBase.IO.EmbeddedResource.GetBytes("Continuum.Test.Samples.weather-simulation.continuum", Assembly.GetExecutingAssembly());
            var endOfHeader = 0L;

            using (var ms = new MemoryStream(bytes))
            {
                var reader = new CaptureReader(new ConcurrentStream(ms), new StateResolver());

                endOfHeader = reader.BaseStream.Position;
            }

            var stream = new MemoryStream();
            var baseStream = new ConcurrentStream(stream);
            var binaryWriter = new BinaryWriter(stream);
            var stateResolver = new StateResolver();
            stateResolver.Add(new Continuum.Test.Mock.WeatherStateController(new WeatherSimulator()));

            //push in some bytes to get it started, enough for the header so that the stream won't throw on construction
            binaryWriter.Write(bytes, 0, (int)endOfHeader);

            var offset = baseStream.Position;
            baseStream.Position = 0;

            var captureStream = new CaptureStream(baseStream, FileAccess.Read, stateResolver);

            Assert.Null(captureStream.Peek());

            //write some bytes in (not enough for a full state)
            binaryWriter.Seek((int)offset, SeekOrigin.Begin);
            binaryWriter.Write(bytes, (int)offset, 10);

            offset += 10;

            Assert.Null(captureStream.Peek());

            //write some more bytes so that there is now a full state that can be peeked at
            binaryWriter.Seek((int)offset, SeekOrigin.Begin);
            binaryWriter.Write(bytes, (int)offset, 200);

            Assert.NotNull(captureStream.Peek());
        }
        public void State_Allocation_Table_Is_Correctly_Populated()
        {
            var expectedId = (short)123;
            var expectedGuid = Guid.NewGuid();

            var ms = new ConcurrentStream(new MemoryStream());
            var idBytes = BitConverter.GetBytes(expectedId);
            var guidBytes = expectedGuid.ToByteArray();

            //write the header
            var header = _CreateContinuumHeader(1000, 10000);
            ms.Write(header.ToArray(), 0, header.Length);

            //write the SAT
            ms.Write(BitConverter.GetBytes(1), 0, 4);
            ms.Write(idBytes, 0, idBytes.Length);
            ms.Write(guidBytes, 0, guidBytes.Length);

            //rewind the stream
            ms.Position = 0;

            var stateController = new Mock<IStateController>();
            var stateResolver = new Mock<IStateResolver>();

            stateResolver.Setup(s => s.Find(It.IsAny<Guid>())).Returns(stateController.Object);

            var captureReader = new CaptureReader(ms, stateResolver.Object);

            Assert.NotEmpty(captureReader.StateAllocationTable);
            Assert.Equal(expectedId, captureReader.StateAllocationTable.First().Key);
            Assert.Equal(expectedGuid, captureReader.StateAllocationTable.First().Value);
            Assert.Equal(1, captureReader.StateAllocationTable.Count);
        }
        public void Peek_Does_Not_Advance_The_Read_Pointer()
        {
            var writeOperations = 100;
            var ms = new ConcurrentStream(new MemoryStream());

            var sat = new Dictionary<Guid, short>();
            sat.Add(Guid.NewGuid(), 24);
            sat.Add(Guid.NewGuid(), 25);
            sat.Add(Guid.NewGuid(), 26);

            var stateResolver = new Mock<IStateResolver>();
            stateResolver.SetupGet(s => s.AllocationTable).Returns(sat);
            stateResolver.Setup(s => s.IsAllocated(It.IsAny<Guid>())).Returns<Guid>(g => sat.ContainsKey(g));
            stateResolver.Setup(s => s.GetAllocatedId(It.IsAny<Guid>())).Returns<Guid>(g => sat[g]);

            //write operations
            var captureWriter = new CaptureWriter(ms, stateResolver.Object);

            for (int i = 0; i < writeOperations; i++)
            {
                var timestamp = DateTime.UtcNow;
                var randomData = new byte[1024];
                new Random().NextBytes(randomData);

                var randomSat = (short)new Random().Next(24, 27);

                var captureState = new Mock<ICaptureState>();
                captureState.Setup(c => c.Data).Returns(randomData);
                captureState.Setup(c => c.Guid).Returns(sat.Where(f => f.Value == randomSat).First().Key);
                captureState.Setup(c => c.Timestamp).Returns(timestamp);

                captureWriter.Write(captureState.Object);
            }

            //rewind the stream to the beginning
            ms.Position = 0;

            //read operations
            var readStateResolver = new StateResolver();
            readStateResolver.Add(new SimpleStateController { Guid = sat.Where(f => f.Value == 24).First().Key });
            readStateResolver.Add(new SimpleStateController { Guid = sat.Where(f => f.Value == 25).First().Key });
            readStateResolver.Add(new SimpleStateController { Guid = sat.Where(f => f.Value == 26).First().Key });

            var captureReader = new CaptureReader(ms, readStateResolver);

            var position = captureReader.Position;
            var state = captureReader.Peek(sat.Where(f => f.Value == (short)26).First().Key);

            Assert.NotNull(state);
            Assert.Equal(position, captureReader.Position);
        }
        public void CaptureReader_Throws_An_Exception_When_Loading_An_Invalid_Continuum_Stream()
        {
            //empty stream is considered invalid
            var baseStream = new ConcurrentStream(new MemoryStream());

            var stateController = new Mock<IStateController>();
            var stateResolver = new Mock<IStateResolver>();

            stateResolver.Setup(s => s.Find(It.IsAny<Guid>())).Returns(stateController.Object);

            try
            {
                var captureReader = new CaptureReader(baseStream, stateResolver.Object);

                //fail
                Assert.True(false);
            }
            catch
            {
                //pass
                Assert.True(true);
            }
        }
        public void CaptureReader_Selects_The_Correct_IStateController_During_Reads()
        {
            var immlStateController = new Mock<IStateController>();
            var immlStateControllerId = (short)100;
            var immlStateControllerGuid = Guid.NewGuid();
            immlStateController.Setup(g => g.Guid).Returns(immlStateControllerGuid);

            var boneNodeStateController = new Mock<IStateController>();
            var boneNodeStateControllerId = (short)123;
            var boneNodeStateControllerGuid = Guid.NewGuid();
            boneNodeStateController.Setup(g => g.Guid).Returns(boneNodeStateControllerGuid);

            //build 2 different state mappings
            var ms = new ConcurrentStream(new MemoryStream());

            //header
            var header = _CreateContinuumHeader(1000, 10000);
            ms.Write(header, 0, header.Length);

            //sat
            ms.Write(BitConverter.GetBytes(2), 0, 4); //count

            //mapping for imml
            ms.Write(BitConverter.GetBytes(immlStateControllerId), 0, 2);
            ms.Write(immlStateControllerGuid.ToByteArray(), 0, 16);

            //mapping for bones
            ms.Write(BitConverter.GetBytes(boneNodeStateControllerId), 0, 2);
            ms.Write(boneNodeStateControllerGuid.ToByteArray(), 0, 16);

            //generate 2 dummy states, one for each controller
            var firstRandomBytes = new byte[1024];
            new Random().NextBytes(firstRandomBytes);

            ms.Write(BitConverter.GetBytes(immlStateControllerId), 0, 2);
            ms.Write(BitConverter.GetBytes(DateTime.UtcNow.ToBinary()), 0, 8);
            ms.Write(BitConverter.GetBytes((int)firstRandomBytes.Length), 0, 4);
            ms.Write(firstRandomBytes, 0, firstRandomBytes.Length);

            var secondRandomBytes = new byte[2048];
            new Random().NextBytes(secondRandomBytes);

            ms.Write(BitConverter.GetBytes(boneNodeStateControllerId), 0, 2);
            ms.Write(BitConverter.GetBytes(DateTime.UtcNow.ToBinary()), 0, 8);
            ms.Write(BitConverter.GetBytes((int)secondRandomBytes.Length), 0, 4);
            ms.Write(secondRandomBytes, 0, secondRandomBytes.Length);

            ms.Position = 0;

            //perform the reads and verify
            var stateResolver = new StateResolver();
            stateResolver.Add(immlStateController.Object);
            stateResolver.Add(boneNodeStateController.Object);

            var captureReader = new CaptureReader(ms, stateResolver);
            captureReader.Read();
            captureReader.Read();

            boneNodeStateController.Verify(c => c.Create(It.IsAny<byte[]>(), It.IsAny<DateTime>(), It.IsAny<double>()), Times.Once());
            immlStateController.Verify(c => c.Create(It.IsAny<byte[]>(), It.IsAny<DateTime>(), It.IsAny<double>()), Times.Once());
        }
        public void CaptureReader_Loads_A_Valid_Continuum_Stream()
        {
            var satCount = 5;
            var header = _CreateContinuumHeader(1000, 10000);
            var sat = _CreateSAT(satCount);

            var baseStream = new ConcurrentStream(new MemoryStream());
            baseStream.Write(header.ToArray(), 0, header.Length);
            baseStream.Write(sat, 0, sat.Length);
            baseStream.Position = 0;

            var stateController = new Mock<IStateController>();
            var stateResolver = new Mock<IStateResolver>();

            stateResolver.Setup(s => s.Find(It.IsAny<Guid>())).Returns(stateController.Object);

            var captureReader = new CaptureReader(baseStream, stateResolver.Object);

            Assert.Equal(satCount, captureReader.StateAllocationTable.Count);
        }
        public void CaptureStream_Supports_Reading_A_File_While_It_Is_Being_Written_From_Another_Thread()
        {
            //base bytes to feed into the stream at random
            var bytes = VastPark.FrameworkBase.IO.EmbeddedResource.GetBytes("Continuum.Test.Samples.weather-simulation.continuum", Assembly.GetExecutingAssembly());
            var endOfHeader = 0L;

            using(var ms = new MemoryStream(bytes))
            {
                var reader = new CaptureReader(new ConcurrentStream(ms), new StateResolver());

                endOfHeader = reader.BaseStream.Position;
            }

            var stream = new MemoryStream();
            var baseStream = new ConcurrentStream(stream);
            var binaryWriter = new BinaryWriter(stream);
            var stateResolver = new StateResolver();
            stateResolver.Add(new Continuum.Test.Mock.WeatherStateController(new WeatherSimulator()));

            //push in some bytes to get it started, enough for the header so that the stream won't throw on construction
            binaryWriter.Write(bytes, 0, (int)endOfHeader);

            var offset = baseStream.Position;
            baseStream.Position = 0;

            var captureStream = new CaptureStream(baseStream, FileAccess.Read, stateResolver);

            //write in a little more so we don't have a full state yet
            binaryWriter.Seek((int)offset, SeekOrigin.Begin);
            //binaryWriter.Write(bytes, (int)offset, 5);

            //offset += 5;

            var readStates = 0;
            var lockObject = new object();

            //create a thread to randomly write chunks of bytes into the base stream
            ThreadPool.QueueUserWorkItem(w =>
            {
                while (offset < bytes.LongLength)
                {
                    var bytesToWrite = new Random().Next(1, 200);

                    if (bytesToWrite > bytes.Length - offset)
                    {
                        bytesToWrite = Convert.ToInt32(bytes.LongLength - offset);
                    }

                    lock (lockObject)
                    {
                        binaryWriter.Seek((int)offset, SeekOrigin.Begin);
                        binaryWriter.Write(bytes, (int)offset, bytesToWrite);
                        offset += bytesToWrite;
                    }

                    Thread.Sleep(200);
                }

                Assert.Equal(bytes.LongLength, baseStream.Length);

                lock (lockObject)
                {
                    binaryWriter.Seek(0, SeekOrigin.Begin);

                    for (int i = 0; i < bytes.LongLength; i++)
                    {
                        Assert.Equal(bytes[i], (byte)baseStream.ReadByte());
                    }
                }
            });

            while (captureStream.Position < captureStream.Count)
            {
                lock (lockObject)
                {
                    if (captureStream.Peek() != null)
                    {
                        captureStream.Read();
                        readStates++;
                    }
                }
            }

            Assert.Equal(captureStream.Count, readStates);
        }