private void NodeTreeChecker(int chunkCount, int expectedNodeCount, uint expectedHeight, string expectedHash)
        {
            var r            = new Random(Seed: 0);
            var actualChunks = Enumerable
                               .Range(0, chunkCount)
                               .Select(i =>
            {
                unchecked
                {
                    byte[] hash = new byte[32];
                    r.NextBytes(hash);
                    hash[0] = (byte)i;
                    hash[1] = (byte)(i >> 8);
                    hash[2] = (byte)(i >> 16);
                    hash[3] = (byte)(i >> 24);

                    return(new ChunkInfo(0, 64 * 1024, hash));
                }
            })
                               .ToList();

            var node = DedupNodeTree.Create(actualChunks);

            Assert.Equal <string>(expectedHash, node.Hash.ToHex());
            Assert.NotNull(node.Height);
            Assert.Equal(expectedHeight, node.Height.Value);
            var nodes      = node.EnumerateInnerNodesDepthFirst().ToList();
            var nodeChunks = node.EnumerateChunkLeafsInOrder().ToList();

            var node2 = PackedDedupNodeTree.EnumerateTree(actualChunks).Last();

            Assert.Equal(node.Hash.ToHex(), node2.Hash.ToHex());

            foreach (var n in nodes)
            {
                var roundTrip = DedupNode.Deserialize(n.Serialize());
                Assert.Equal(n.Hash, roundTrip.Hash, ByteArrayComparer.Instance);
                Assert.Equal(n.ChildNodes.Count, roundTrip.ChildNodes.Count);
                Assert.True(
                    n.ChildNodes.Zip(roundTrip.ChildNodes, (e1, e2) =>
                {
                    if (e1.Type != e2.Type)
                    {
                        return(false);
                    }
                    else if (e1.TransitiveContentBytes != e2.TransitiveContentBytes)
                    {
                        return(false);
                    }
                    else if (!ByteArrayComparer.Instance.Equals(e1.Hash, e2.Hash))
                    {
                        return(false);
                    }

                    return(true);
                }).All(result => result));
            }

            Assert.Equal(
                actualChunks.Select(c => c.Hash.ToHex()),
                nodeChunks.Select(c => c.Hash.ToHex()));
            Assert.Equal(chunkCount, nodeChunks.Count);
            Assert.Equal(expectedNodeCount, nodes.Count);
        }
예제 #2
0
        private void ChunksEnumeratedAsFileIsRead(Func <IChunker> chunkerFactory)
        {
            var chunks = new List <ChunkInfo>();

            byte[] bytes = new byte[4 * Chunker.MinPushBufferSize];

            var r = new Random(Seed: 0);

            r.NextBytes(bytes);

            using (var chunker = DedupNodeHashAlgorithm.CreateChunker())
                using (var session = chunker.BeginChunking(chunk =>
                {
                    chunks.Add(chunk);
                }))
                {
                    int pushSize       = 2 * (int)Chunker.MinPushBufferSize;
                    int lastChunkCount = 0;
                    for (int i = 0; i < bytes.Length; i += pushSize)
                    {
                        session.PushBuffer(bytes, i, Math.Min(pushSize, bytes.Length - i));
                        Assert.True(chunks.Count > lastChunkCount);
                        lastChunkCount = chunks.Count;
                    }
                }

            string[] expectedChunkHashes = chunks.Select(c => c.Hash.ToHex()).ToArray();

            DedupNode rootFromhash;

            string[] actualChunkHashes;
            using (var hasher = new DedupNodeHashAlgorithm())
            {
                hasher.ComputeHash(bytes);
                rootFromhash      = hasher.GetNode();
                actualChunkHashes = rootFromhash.EnumerateChunkLeafsInOrder().Select(c => c.Hash.ToHex()).ToArray();
                Assert.Equal(expectedChunkHashes, actualChunkHashes);
            }

            var seenNodes = new HashSet <byte[]>(chunks.Select(c => c.Hash), ByteArrayComparer.Instance);

            DedupNode?root = null;

            foreach (var node in PackedDedupNodeTree.EnumerateTree(chunks)
                     .Where(n => n.Type != DedupNode.NodeType.ChunkLeaf))
            {
                foreach (var child in node.ChildNodes)
                {
                    Assert.True(seenNodes.Contains(child.Hash));
                }

                Assert.True(seenNodes.Add(node.Hash));
                root = node;
            }

            Assert.True(root.HasValue);

            // ReSharper disable once PossibleInvalidOperationException
            Assert.Equal(rootFromhash, root.Value);
            actualChunkHashes = root.Value.EnumerateChunkLeafsInOrder().Select(c => c.Hash.ToHex()).ToArray();
            Assert.Equal(expectedChunkHashes, actualChunkHashes);
        }