public async Task WhenContainer_FullLiveCycle_ShouldPass()
        {
            var container = new BlobRepository(_blobStore);

            await container.CreateContainer(_workContext);

            IReadOnlyList <string> filePaths = await container.List(_workContext, "*");

            await filePaths.ForEachAsync(x => container.Delete(_workContext, x));

            const string filePath = "testBlob";
            const string data     = "This is data";
            await container.Set(_workContext, filePath, data);

            filePaths = await container.List(_workContext, "*");

            filePaths.Should().NotBeNull();
            filePaths.Count.Should().Be(1);
            filePaths[0].Should().Be(filePath);

            string readData = await container.Get(_workContext, filePath);

            readData.Should().NotBeNullOrWhiteSpace();
            readData.Should().Be(data);

            await container.Delete(_workContext, filePath);

            filePaths = await container.List(_workContext, "*");

            filePaths.Should().NotBeNull();
            filePaths.Count.Should().Be(0);
        }
        public async Task WhenContainer_FullLiveCycleForFiles_ShouldPass()
        {
            var container = new BlobRepository(_blobStore);

            await container.CreateContainer(_workContext);

            IReadOnlyList <string> filePaths = await container.List(_workContext, "*");

            await filePaths.ForEachAsync(x => container.Delete(_workContext, x));

            const int count    = 10;
            var       dataList = Enumerable.Range(0, count)
                                 .Select(x => new { File = $"File_{x}", Data = $"Data_{x}" })
                                 .ToList();

            await dataList.ForEachAsync(x => container.Set(_workContext, x.File, x.Data));

            filePaths = await container.List(_workContext, "*");

            filePaths.Should().NotBeNull();
            filePaths.Count.Should().Be(count);

            await dataList.ForEachAsync(x => container.Delete(_workContext, x.File));

            filePaths = await container.List(_workContext, "*");

            filePaths.Should().NotBeNull();
            filePaths.Count.Should().Be(0);
        }
        public async Task GivenBlockChain_WhenUsingBuilder_ShouldValidate()
        {
            const string _blobPath = "Test.sa";

            var container = new BlobRepository(_blobStore);

            await container.CreateContainer(_workContext);

            var blockChain = new BlockChain()
            {
                new DataBlock <HeaderBlock>("header", "header_1", new HeaderBlock("Master Contract")),
                new DataBlock <BlobBlock>("contract", "contract_1", new BlobBlock("contract.docx", "docx", "me", Encoding.UTF8.GetBytes("this is a contract between two people"))),
                new DataBlock <TrxBlock>("ContractLedger", "Pmt", new TrxBlock("1", "cr", 100)),
            };

            blockChain.Blocks.Count.Should().Be(4);

            string blockChainHash = blockChain.ToMerkleTree().BuildTree().ToString();

            using var zipStream = blockChain.ToZipContainer(_workContext);

            BlockChain result = zipStream.ToBlockChain(_workContext);

            result.IsValid().Should().BeTrue();
            string resultChainHash = result.ToMerkleTree().BuildTree().ToString();

            blockChainHash.Should().Be(resultChainHash);

            await container.Delete(_workContext, _blobPath);
        }
        public async Task GivenBlockChain_WhenContainerIsBlob_ShouldRoundTrip()
        {
            const string _zipPath  = "$block";
            const string _blobPath = "Test.sa";

            var container = new BlobRepository(_blobStore);

            await container.CreateContainer(_workContext);

            var blockChain = new BlockChain()
            {
                new DataBlock <HeaderBlock>("header", "header_1", new HeaderBlock("Master Contract")),
                new DataBlock <BlobBlock>("contract", "contract_1", new BlobBlock("contract.docx", "docx", "me", Encoding.UTF8.GetBytes("this is a contract between two people"))),
                new DataBlock <TrxBlock>("ContractLedger", "Pmt", new TrxBlock("1", "cr", 100)),
            };

            blockChain.Blocks.Count.Should().Be(4);
            blockChain.IsValid().Should().BeTrue();
            string blockChainHash = blockChain.ToMerkleTree().BuildTree().ToString();

            string json = blockChain.ToJson();

            //var buffer = new byte[1000];
            using var writeMemoryBuffer = new MemoryStream();
            var writer = new ZipContainerWriter(new ZipArchive(writeMemoryBuffer, ZipArchiveMode.Create, leaveOpen: true));

            writer.Write(_workContext, _zipPath, json);
            writer.Close();

            writeMemoryBuffer.Length.Should().BeGreaterThan(0);
            writeMemoryBuffer.Seek(0, SeekOrigin.Begin);

            await container.Delete(_workContext, _blobPath);

            await container.Upload(_workContext, _blobPath, writeMemoryBuffer);

            writeMemoryBuffer.Close();

            IReadOnlyList <byte> readBlob = await container.Download(_workContext, _blobPath);

            using var readMemoryBuffer = new MemoryStream(readBlob.ToArray());

            var    reader   = new ZipContainerReader(new ZipArchive(readMemoryBuffer, ZipArchiveMode.Read));
            string readJson = reader.Read(_workContext, _zipPath);

            reader.Close();

            BlockChain result = readJson.ToBlockChain();

            result.IsValid().Should().BeTrue();
            string resultChainHash = result.ToMerkleTree().BuildTree().ToString();

            blockChainHash.Should().Be(resultChainHash);

            await container.Delete(_workContext, _blobPath);
        }
        public async Task GivenFileDoesNotExist_WhenGet_ShouldThrow()
        {
            var container = new BlobRepository(_blobStore);

            await container.CreateContainer(_workContext);

            IReadOnlyList <string> filePaths = await container.List(_workContext, "*");

            await filePaths.ForEachAsync(x => container.Delete(_workContext, x));

            const string filePath = "testBlob";
            Func <Task>  act      = async() => await container.Get(_workContext, filePath);

            await act.Should().ThrowAsync <RequestFailedException>();
        }
        public async Task GivenBlockChain_WhenContainerIsBlobAndBuilder_ShouldRoundTrip()
        {
            const string _blobPath = "Test.sa";

            var container = new BlobRepository(_blobStore);

            await container.CreateContainer(_workContext);

            var blockChain = new BlockChain()
            {
                new DataBlock <HeaderBlock>("header", "header_1", new HeaderBlock("Master Contract")),
                new DataBlock <BlobBlock>("contract", "contract_1", new BlobBlock("contract.docx", "docx", "me", Encoding.UTF8.GetBytes("this is a contract between two people"))),
                new DataBlock <TrxBlock>("ContractLedger", "Pmt", new TrxBlock("1", "cr", 100)),
            };

            blockChain.Blocks.Count.Should().Be(4);
            string blockChainHash = blockChain.ToMerkleTree().BuildTree().ToString();

            using (var zipStream = blockChain.ToZipContainer(_workContext))
            {
                await container.Delete(_workContext, _blobPath);

                await container.Upload(_workContext, _blobPath, zipStream);
            }

            IReadOnlyList <byte> readBlob = await container.Download(_workContext, _blobPath);

            using var readMemoryBuffer = new MemoryStream(readBlob.ToArray());

            BlockChain result = readMemoryBuffer.ToBlockChain(_workContext);

            result.IsValid().Should().BeTrue();
            string resultChainHash = result.ToMerkleTree().BuildTree().ToString();

            blockChainHash.Should().Be(resultChainHash);

            await container.Delete(_workContext, _blobPath);
        }
        public async Task WhenContainer_CreateIfItDoesNotExist_ShouldPass()
        {
            var subject = new BlobRepository(_blobStore);

            await subject.CreateContainer(_workContext);
        }