[InlineData(DedupNode.MaxDirectChildrenPerNode / 2, 16, 1)] // 1MB public void HashOfChunksInNodeMatchesChunkHashAlgorithm(int expectedChunkCount, int multiplier, int divider) { var config = new ChunkerConfiguration((multiplier * ChunkerConfiguration.Default.AvgChunkSize) / divider); HashOfChunksInNodeMatchesChunkHashAlgorithmInner(expectedChunkCount, config, new ManagedChunker(config)); if (Chunker.IsComChunkerSupported && config.AvgChunkSize == ChunkerConfiguration.Default.AvgChunkSize) { HashOfChunksInNodeMatchesChunkHashAlgorithmInner(expectedChunkCount, config, new ComChunker(config)); } }
[InlineData(DedupNode.MaxDirectChildrenPerNode / 8, 64, 1)] // 4MB public void HashOfChunksInNodeMatchesChunkHashAlgorithmNegative(int expectedChunkCount, int multiplier, int divider) { var config = new ChunkerConfiguration((multiplier * ChunkerConfiguration.Default.AvgChunkSize) / divider); Assert.Throws <NotImplementedException>(() => HashOfChunksInNodeMatchesChunkHashAlgorithmInner(expectedChunkCount, config, new ManagedChunker(config))); if (Chunker.IsComChunkerSupported && config.AvgChunkSize == ChunkerConfiguration.Default.AvgChunkSize) { Assert.Throws <NotImplementedException>(() => HashOfChunksInNodeMatchesChunkHashAlgorithmInner(expectedChunkCount, config, new ComChunker(config))); } }
[InlineData(HashType.Dedup1024K, DedupNode.MaxDirectChildrenPerNode / 8, 64, 16)] // 4MB | 64 * 4 * 1024K 256MB public void HashOfChunksInNodeMatchesChunkHashAlgorithmNegative(HashType hashType, int expectedChunkCount, int multiplier, int divider) { Assert.True(hashType.IsValidDedup(), $"Hash type: {hashType} is not a valid dedup."); var config = new ChunkerConfiguration((multiplier * hashType.GetAvgChunkSize()) / divider); Assert.Throws <NotImplementedException>(() => HashOfChunksInNodeMatchesChunkHashAlgorithmInner(expectedChunkCount, config, new ManagedChunker(config))); if (Chunker.IsComChunkerSupported && config.AvgChunkSize == ChunkerConfiguration.SupportedComChunkerConfiguration.AvgChunkSize && hashType == HashType.Dedup64K) // No COMchunker support for any other chunk sizes. { Assert.Throws <NotImplementedException>(() => HashOfChunksInNodeMatchesChunkHashAlgorithmInner(expectedChunkCount, config, new ComChunker(config))); } }
private void HashOfChunksInNodeMatchesChunkHashAlgorithmInner(int expectedChunkCount, ChunkerConfiguration config, IChunker chunker) { using (DedupNodeOrChunkHashAlgorithm nodeHasher = new DedupNodeOrChunkHashAlgorithm(chunker)) using (DedupChunkHashAlgorithm chunkHasher = new DedupChunkHashAlgorithm()) { byte[] bytes = new byte[expectedChunkCount * config.AvgChunkSize]; nodeHasher.SetInputLength(bytes.Length); var r = new Random(Seed: 0); r.NextBytes(bytes); nodeHasher.ComputeHash(bytes, 0, bytes.Length); var node = nodeHasher.GetNode(); Assert.NotNull(node.Height); if (expectedChunkCount >= 2 * DedupNode.MaxDirectChildrenPerNode) { Assert.Equal((uint)2, node.Height.Value); } ulong offset = 0; int chunkCount = 0; foreach (var chunkInNode in node.EnumerateChunkLeafsInOrder()) { byte[] chunkHash = chunkHasher.ComputeHash(bytes, (int)offset, (int)chunkInNode.TransitiveContentBytes); Assert.Equal(chunkHash.ToHex(), chunkInNode.Hash.ToHex()); offset += chunkInNode.TransitiveContentBytes; chunkCount += 1; } Assert.Equal(offset, node.TransitiveContentBytes); double ratio = (1.0 * expectedChunkCount) / chunkCount; Assert.True(Math.Abs(ratio - 1.0) < 0.3); // within 30% of expected } }