我正在使用GZipStream来压缩/解压数据。我选择它而不是DeflateStream,因为文档说明GZipStream还添加了CRC以检测损坏的数据,这是我想要的另一个功能。我的“正面”单元测试效果很好,因为我可以压缩一些数据,保存压缩的字节数组,然后成功地再次解压缩它。.NET GZipStream compress and decompress problem帖子帮助我意识到在访问压缩或解压缩数据之前需要关闭GZipStream。
接下来,我继续编写“负面”单元测试,以确保可以检测到损坏的数据。我之前使用了MSDN的GZipStream类示例来压缩文件,用文本编辑器打开压缩文件,更改一个字节以使其损坏(好像用文本编辑器打开它已经够糟糕的了!),保存并解压缩它,以确保我得到了预期的InvalidDataException异常。
当我写单元测试时,我选择了一个任意的字节进行损坏(例如,compressedDataBytes[50] = 0x99),然后得到了一个InvalidDataException异常。到目前为止还不错。我很好奇,所以我选择了另一个字节,但令我惊讶的是我没有得到异常。这可能是可以接受的(例如,我巧合地命中了数据块中未使用的字节),只要数据仍然可以成功恢复。然而,我也没有得到正确的数据!
为了确保“不是我”的问题,我从.NET GZipStream compress and decompress problem底部清理过的代码,并修改为按顺序破坏压缩数据中的每个字节,直到无法正确解压缩为止。以下是更改(请注意,我正在使用Visual Studio 2010测试框架):
当我运行这个测试时,我得到:
所以,这意味着实际上有7个案例,在这些案例中破坏数据并没有产生影响(字符串成功恢复),但是破坏第11个字节既没有抛出异常,也没有恢复数据。
我是否遗漏了什么或做错了什么?有人能看出为什么无法检测到损坏的压缩数据吗?
接下来,我继续编写“负面”单元测试,以确保可以检测到损坏的数据。我之前使用了MSDN的GZipStream类示例来压缩文件,用文本编辑器打开压缩文件,更改一个字节以使其损坏(好像用文本编辑器打开它已经够糟糕的了!),保存并解压缩它,以确保我得到了预期的InvalidDataException异常。
当我写单元测试时,我选择了一个任意的字节进行损坏(例如,compressedDataBytes[50] = 0x99),然后得到了一个InvalidDataException异常。到目前为止还不错。我很好奇,所以我选择了另一个字节,但令我惊讶的是我没有得到异常。这可能是可以接受的(例如,我巧合地命中了数据块中未使用的字节),只要数据仍然可以成功恢复。然而,我也没有得到正确的数据!
为了确保“不是我”的问题,我从.NET GZipStream compress and decompress problem底部清理过的代码,并修改为按顺序破坏压缩数据中的每个字节,直到无法正确解压缩为止。以下是更改(请注意,我正在使用Visual Studio 2010测试框架):
// successful compress / decompress example code from:
// https://dev59.com/pnI-5IYBdhLWcg3w99kH
[TestMethod]
public void Test_zipping_with_memorystream_and_corrupting_compressed_data()
{
const string sample = "This is a compression test of microsoft .net gzip compression method and decompression methods";
var encoding = new ASCIIEncoding();
var data = encoding.GetBytes(sample);
string sampleOut = null;
byte[] cmpData;
// Compress
using (var cmpStream = new MemoryStream())
{
using (var hgs = new GZipStream(cmpStream, CompressionMode.Compress))
{
hgs.Write(data, 0, data.Length);
}
cmpData = cmpStream.ToArray();
}
int corruptBytesNotDetected = 0;
// corrupt data byte by byte
for (var byteToCorrupt = 0; byteToCorrupt < cmpData.Length; byteToCorrupt++)
{
// corrupt the data
cmpData[byteToCorrupt]++;
using (var decomStream = new MemoryStream(cmpData))
{
using (var hgs = new GZipStream(decomStream, CompressionMode.Decompress))
{
using (var reader = new StreamReader(hgs))
{
try
{
sampleOut = reader.ReadToEnd();
// if we get here, the corrupt data was not detected by GZipStream
// ... okay so long as the correct data is extracted
corruptBytesNotDetected++;
var message = string.Format("ByteCorrupted = {0}, CorruptBytesNotDetected = {1}",
byteToCorrupt, corruptBytesNotDetected);
Assert.IsNotNull(sampleOut, message);
Assert.AreEqual(sample, sampleOut, message);
}
catch(InvalidDataException)
{
// data was corrupted, so we expect to get here
}
}
}
}
// restore the data
cmpData[byteToCorrupt]--;
}
}
当我运行这个测试时,我得到:
Assert.AreEqual failed. Expected:<This is a compression test of microsoft .net gzip compression method and decompression methods>. Actual:<>. ByteCorrupted = 11, CorruptBytesNotDetected = 8
所以,这意味着实际上有7个案例,在这些案例中破坏数据并没有产生影响(字符串成功恢复),但是破坏第11个字节既没有抛出异常,也没有恢复数据。
我是否遗漏了什么或做错了什么?有人能看出为什么无法检测到损坏的压缩数据吗?