Skip to content

Commit f89f20a

Browse files
committed
more unit test, changed pbkdf2 iterations count, added documentation, some code cleanup
1 parent 9a7a721 commit f89f20a

35 files changed

+773
-85
lines changed

Blazer.Net.Tests/BigDataTests.cs

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
using System;
2+
using System.Diagnostics;
3+
using System.IO;
4+
5+
using Force.Blazer;
6+
7+
using NUnit.Framework;
8+
9+
namespace Blazer.Net.Tests
10+
{
11+
[TestFixture]
12+
public class BigDataTests
13+
{
14+
[Test]
15+
[Ignore("Slow for usual run")]
16+
public void Large_Data_Should_Be_Compressed()
17+
{
18+
var outs = new MemoryStream();
19+
// stream algorithm is affected to big data (requires backref shift)
20+
var blazerCompressionOptions = BlazerCompressionOptions.CreateStream();
21+
blazerCompressionOptions.LeaveStreamOpen = true;
22+
var comp = new BlazerInputStream(outs, blazerCompressionOptions);
23+
const int BufSize = 200000;
24+
var buf = new byte[BufSize];
25+
long totalSize = 1L << 32; // 4Gb
26+
var iterations = totalSize / buf.Length;
27+
totalSize = iterations * buf.Length;
28+
for (var i = 0; i < iterations; i++)
29+
{
30+
var v = i % 256;
31+
for (var k = 0; k < buf.Length; k++) buf[k] = (byte)v;
32+
comp.Write(buf, 0, buf.Length);
33+
}
34+
35+
comp.Close();
36+
37+
Debug.WriteLine("Compressed. " + outs.Length);
38+
39+
outs.Seek(0, SeekOrigin.Begin);
40+
var decomp = new BlazerOutputStream(outs);
41+
long totalPos = 0;
42+
while (true)
43+
{
44+
var readed = decomp.Read(buf, 0, buf.Length);
45+
if (readed == 0) break;
46+
for (var i = 0; i < readed; i++)
47+
{
48+
long v = (totalPos / BufSize) % 256;
49+
if (buf[i] != v)
50+
throw new ArgumentException("Invalid data at " + totalPos + ". Expected: " + v + ", but was: " + buf[i]);
51+
totalPos++;
52+
}
53+
}
54+
55+
Assert.That(totalPos, Is.EqualTo(totalSize));
56+
}
57+
}
58+
}

Blazer.Net.Tests/Blazer.Net.Tests.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@
4444
<Reference Include="System.Xml" />
4545
</ItemGroup>
4646
<ItemGroup>
47+
<Compile Include="BigDataTests.cs" />
4748
<Compile Include="EncryptionTests.cs" />
4849
<Compile Include="IntegrityHelper.cs" />
4950
<Compile Include="IntegrityTests.cs" />

Blazer.Net.Tests/IntegrityTests.cs

Lines changed: 97 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
using System;
2-
using System.Collections.Generic;
32
using System.IO;
4-
using System.Linq;
53
using System.Security.Cryptography;
64
using System.Text;
75

@@ -71,5 +69,102 @@ public void Invalid_Header_Should_Throw_Errors()
7169
Assert.That(Assert.Throws<InvalidOperationException>(() => IntegrityHelper.DecompressData(compressed)).Message, Is.EqualTo("Invalid flag combination. Try to use newer version of Blazer"));
7270
compressed[6]--;
7371
}
72+
73+
[Test]
74+
[TestCase(1, BlazerAlgorithm.NoCompress)]
75+
[TestCase(1, BlazerAlgorithm.Stream)]
76+
[TestCase(1, BlazerAlgorithm.Block)]
77+
[TestCase(2, BlazerAlgorithm.NoCompress)]
78+
[TestCase(2, BlazerAlgorithm.Stream)]
79+
[TestCase(2, BlazerAlgorithm.Block)]
80+
[TestCase(3, BlazerAlgorithm.NoCompress)]
81+
[TestCase(3, BlazerAlgorithm.Stream)]
82+
[TestCase(3, BlazerAlgorithm.Block)]
83+
[TestCase(4, BlazerAlgorithm.NoCompress)]
84+
[TestCase(4, BlazerAlgorithm.Stream)]
85+
[TestCase(4, BlazerAlgorithm.Block)]
86+
public void Small_Block_Sizes_ShouldBe_Handled_WithoutFlush(int blockSize, BlazerAlgorithm algorithm)
87+
{
88+
var data = new byte[blockSize];
89+
data[0] = (byte)blockSize;
90+
var blazerCompressionOptions = BlazerCompressionOptions.CreateStream();
91+
blazerCompressionOptions.SetEncoderByAlgorithm(algorithm);
92+
93+
var memoryStream = new MemoryStream();
94+
const int Count = 10;
95+
using (var stream = new BlazerInputStream(memoryStream, blazerCompressionOptions))
96+
{
97+
for (var i = 0; i < Count; i++)
98+
stream.Write(data, 0, data.Length);
99+
}
100+
101+
var compressed = memoryStream.ToArray();
102+
var decompressed = IntegrityHelper.DecompressData(compressed);
103+
Assert.That(decompressed.Length, Is.EqualTo(Count * data.Length));
104+
}
105+
106+
[Test]
107+
[TestCase(1, BlazerAlgorithm.NoCompress)]
108+
[TestCase(1, BlazerAlgorithm.Stream)]
109+
[TestCase(1, BlazerAlgorithm.Block)]
110+
[TestCase(2, BlazerAlgorithm.NoCompress)]
111+
[TestCase(2, BlazerAlgorithm.Stream)]
112+
[TestCase(2, BlazerAlgorithm.Block)]
113+
[TestCase(3, BlazerAlgorithm.NoCompress)]
114+
[TestCase(3, BlazerAlgorithm.Stream)]
115+
[TestCase(3, BlazerAlgorithm.Block)]
116+
[TestCase(4, BlazerAlgorithm.NoCompress)]
117+
[TestCase(4, BlazerAlgorithm.Stream)]
118+
[TestCase(4, BlazerAlgorithm.Block)]
119+
public void Small_Block_Sizes_ShouldBe_Handled_WithFlush(int blockSize, BlazerAlgorithm algorithm)
120+
{
121+
var data = new byte[blockSize];
122+
data[0] = (byte)blockSize;
123+
var blazerCompressionOptions = BlazerCompressionOptions.CreateStream();
124+
blazerCompressionOptions.SetEncoderByAlgorithm(algorithm);
125+
blazerCompressionOptions.RespectFlush = true;
126+
127+
var memoryStream = new MemoryStream();
128+
const int Count = 10;
129+
using (var stream = new BlazerInputStream(memoryStream, blazerCompressionOptions))
130+
{
131+
for (var i = 0; i < Count; i++)
132+
{
133+
stream.Write(data, 0, data.Length);
134+
stream.Flush();
135+
}
136+
}
137+
138+
var compressed = memoryStream.ToArray();
139+
var decompressed = IntegrityHelper.DecompressData(compressed);
140+
Assert.That(decompressed.Length, Is.EqualTo(Count * data.Length));
141+
Assert.That(decompressed[blockSize], Is.EqualTo(blockSize));
142+
}
143+
144+
[Test]
145+
[TestCase(BlazerAlgorithm.NoCompress)]
146+
[TestCase(BlazerAlgorithm.Stream)]
147+
[TestCase(BlazerAlgorithm.Block)]
148+
public void Zero_Block_Sizes_Should_Not_Cause_Error(BlazerAlgorithm algorithm)
149+
{
150+
var data = new byte[0];
151+
var blazerCompressionOptions = BlazerCompressionOptions.CreateStream();
152+
blazerCompressionOptions.SetEncoderByAlgorithm(algorithm);
153+
154+
var memoryStream = new MemoryStream();
155+
const int Count = 10;
156+
using (var stream = new BlazerInputStream(memoryStream, blazerCompressionOptions))
157+
{
158+
for (var i = 0; i < Count; i++)
159+
{
160+
stream.Write(data, 0, data.Length);
161+
stream.Flush();
162+
}
163+
}
164+
165+
var compressed = memoryStream.ToArray();
166+
var decompressed = IntegrityHelper.DecompressData(compressed);
167+
Assert.That(decompressed.Length, Is.EqualTo(0));
168+
}
74169
}
75170
}

Blazer.Net/Algorithms/BlockDecoder.cs

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@
22

33
namespace Force.Blazer.Algorithms
44
{
5+
/// <summary>
6+
/// Decoder of block version of Blazer algorithm
7+
/// </summary>
8+
/// <remarks>This version provides relative good and fast compression but decompression rate is same as compression</remarks>
59
public class BlockDecoder : IDecoder
610
{
711
// should be equal with BlockEncoder
@@ -15,6 +19,9 @@ public class BlockDecoder : IDecoder
1519

1620
private int _maxUncompressedBlockSize;
1721

22+
/// <summary>
23+
/// Decodes given buffer
24+
/// </summary>
1825
public BufferInfo Decode(byte[] buffer, int offset, int length, bool isCompressed)
1926
{
2027
if (!isCompressed)
@@ -24,18 +31,43 @@ public BufferInfo Decode(byte[] buffer, int offset, int length, bool isCompresse
2431
return new BufferInfo(_innerBuffer, 0, outLen);
2532
}
2633

34+
/// <summary>
35+
/// Initializes decoder with information about maximum uncompressed block size
36+
/// </summary>
2737
public void Init(int maxUncompressedBlockSize)
2838
{
2939
_innerBuffer = new byte[maxUncompressedBlockSize];
3040
_maxUncompressedBlockSize = maxUncompressedBlockSize;
3141
}
3242

43+
/// <summary>
44+
/// Returns algorithm id
45+
/// </summary>
3346
public BlazerAlgorithm GetAlgorithmId()
3447
{
3548
return BlazerAlgorithm.Block;
3649
}
3750

38-
public virtual int DecompressBlock(byte[] bufferIn, int bufferInOffset, int bufferInLength, byte[] bufferOut, int bufferOutOffset, int bufferOutLength)
51+
/// <summary>
52+
/// Decompresses block of data
53+
/// </summary>
54+
protected virtual int DecompressBlock(
55+
byte[] bufferIn, int bufferInOffset, int bufferInLength, byte[] bufferOut, int bufferOutOffset, int bufferOutLength)
56+
{
57+
return DecompressBlockExternal(bufferIn, bufferInOffset, bufferInLength, bufferOut, bufferOutOffset, bufferOutLength);
58+
}
59+
60+
/// <summary>
61+
/// Decompresses block of data, can be used independently for byte arrays
62+
/// </summary>
63+
/// <param name="bufferIn">In buffer</param>
64+
/// <param name="bufferInOffset">In buffer offset</param>
65+
/// <param name="bufferInLength">In buffer right offset (offset + count)</param>
66+
/// <param name="bufferOut">Out buffer, should be enough size</param>
67+
/// <param name="bufferOutOffset">Out buffer offset</param>
68+
/// <param name="bufferOutLength">Out buffer maximum right offset (offset + count)</param>
69+
/// <returns>Bytes count of decompressed data</returns>
70+
public static int DecompressBlockExternal(byte[] bufferIn, int bufferInOffset, int bufferInLength, byte[] bufferOut, int bufferOutOffset, int bufferOutLength)
3971
{
4072
var hashArr = new int[HASH_TABLE_LEN + 1];
4173
var idxIn = bufferInOffset;
@@ -127,6 +159,10 @@ public virtual int DecompressBlock(byte[] bufferIn, int bufferInOffset, int buff
127159
return idxOut;
128160
}
129161

162+
/// <summary>
163+
/// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
164+
/// </summary>
165+
/// <filterpriority>2</filterpriority>
130166
public virtual void Dispose()
131167
{
132168
}

Blazer.Net/Algorithms/BlockDecoderNative.cs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,20 @@
33

44
namespace Force.Blazer.Algorithms
55
{
6+
/// <summary>
7+
/// Native implementation of decoder of block version of Blazer algorithm
8+
/// </summary>
9+
/// <remarks>This version provides relative good and fast compression but decompression rate is same as compression</remarks>
610
public class BlockDecoderNative : BlockDecoder
711
{
812
[DllImport(@"Blazer.Native.dll", CallingConvention = CallingConvention.Cdecl)]
913
private static extern int blazer_block_decompress_block(
1014
byte[] bufferIn, int bufferInOffset, int bufferInLength, byte[] bufferOut, int bufferOutOffset, int bufferOutLength);
1115

12-
public override int DecompressBlock(
16+
/// <summary>
17+
/// Decompresses block of data
18+
/// </summary>
19+
protected override int DecompressBlock(
1320
byte[] bufferIn, int bufferInOffset, int bufferInLength, byte[] bufferOut, int idxOut, int bufferOutLength)
1421
{
1522
var res = blazer_block_decompress_block(bufferIn, bufferInOffset, bufferInLength, bufferOut, idxOut, bufferOutLength);

Blazer.Net/Algorithms/BlockEncoder.cs

Lines changed: 33 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,10 @@
33

44
namespace Force.Blazer.Algorithms
55
{
6+
/// <summary>
7+
/// Decoder of block version of Blazer algorithm
8+
/// </summary>
9+
/// <remarks>This version provides relative good and fast compression but decompression rate is same as compression</remarks>
610
public class BlockEncoder : IEncoder
711
{
812
private const int HASH_TABLE_BITS = 16;
@@ -11,29 +15,47 @@ public class BlockEncoder : IEncoder
1115
// carefully selected random number
1216
private const uint Mul = 1527631329;
1317

14-
private int _maxInBlockSize;
15-
18+
/// <summary>
19+
/// Storage for output buffer
20+
/// </summary>
1621
[SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1401:FieldsMustBePrivate", Justification = "Reviewed. Suppression is OK here.")]
1722
protected byte[] _bufferOut;
1823

24+
/// <summary>
25+
/// Encodes given buffer
26+
/// </summary>
1927
public BufferInfo Encode(byte[] buffer, int offset, int length)
2028
{
2129
var cnt = CompressBlock(buffer, offset, length, _bufferOut, 0);
2230
return new BufferInfo(_bufferOut, 0, cnt);
2331
}
2432

33+
/// <summary>
34+
/// Initializes encoder with information about maximum uncompressed block size
35+
/// </summary>
2536
public virtual void Init(int maxInBlockSize)
2637
{
27-
_maxInBlockSize = maxInBlockSize;
2838
_bufferOut = new byte[maxInBlockSize + (maxInBlockSize >> 8) + 3];
2939
}
3040

31-
public virtual int CompressBlock(
41+
/// <summary>
42+
/// Compresses block of data
43+
/// </summary>
44+
protected virtual int CompressBlock(
3245
byte[] bufferIn, int bufferInOffset, int bufferInLength, byte[] bufferOut, int bufferOutOffset)
3346
{
3447
return CompressBlockExternal(bufferIn, bufferInOffset, bufferInLength, bufferOut, bufferOutOffset);
3548
}
3649

50+
/// <summary>
51+
/// Compressed block of data, can be used independently for byte arrays
52+
/// </summary>
53+
/// <param name="bufferIn">In buffer</param>
54+
/// <param name="bufferInOffset">In buffer offset</param>
55+
/// <param name="bufferInLength">In buffer right offset (offset + count)</param>
56+
/// <param name="bufferOut">Out buffer, should be enough size</param>
57+
/// <param name="bufferOutOffset">Out buffer offset</param>
58+
/// <returns>Bytes count of compressed data</returns>
3759
public static int CompressBlockExternal(byte[] bufferIn, int bufferInOffset, int bufferInLength, byte[] bufferOut, int bufferOutOffset)
3860
{
3961
var hashArr = new int[HASH_TABLE_LEN + 1];
@@ -256,11 +278,18 @@ public static int CompressBlockExternal(byte[] bufferIn, int bufferInOffset, int
256278
return idxOut;
257279
}
258280

281+
/// <summary>
282+
/// Returns algorithm id
283+
/// </summary>
259284
public BlazerAlgorithm GetAlgorithmId()
260285
{
261286
return BlazerAlgorithm.Block;
262287
}
263288

289+
/// <summary>
290+
/// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
291+
/// </summary>
292+
/// <filterpriority>2</filterpriority>
264293
public virtual void Dispose()
265294
{
266295
}

0 commit comments

Comments
 (0)