Skip to content

Commit 1c10d87

Browse files
committed
Add test that exercises code with more shards.
Add check for max number of shards in ReedSolomon constructor.
1 parent 2fe5b59 commit 1c10d87

File tree

2 files changed

+39
-11
lines changed

2 files changed

+39
-11
lines changed

src/main/java/com/backblaze/erasure/ReedSolomon.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,15 @@ public static ReedSolomon create(int dataShardCount, int parityShardCount) {
3434
* Initializes a new encoder/decoder, with a chosen coding loop.
3535
*/
3636
public ReedSolomon(int dataShardCount, int parityShardCount, CodingLoop codingLoop) {
37+
38+
// The academic papers say that the Vandermonde matrix is only
39+
// guaranteed up to 256 rows. In practice, the tests pass
40+
// up to 248 data + 256 parity, but I don't understand the math
41+
// well enough to trust that.
42+
if (256 < dataShardCount + parityShardCount) {
43+
throw new IllegalArgumentException("too many shards - max is 256");
44+
}
45+
3746
this.dataShardCount = dataShardCount;
3847
this.parityShardCount = parityShardCount;
3948
this.codingLoop = codingLoop;

src/test/java/com/backblaze/erasure/ReedSolomonTest.java

Lines changed: 30 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,25 @@ public void testSimpleEncodeDecode() {
8181
new byte [] { 2, 4 },
8282
new byte [] { 3, 5 }
8383
};
84-
runEncodeDecode(dataShards);
84+
runEncodeDecode(5, 5, dataShards);
85+
}
86+
87+
/**
88+
* Try encoding and decoding with a lot of shards.
89+
*/
90+
@Test
91+
public void testBigEncodeDecode() {
92+
final Random random = new Random(0);
93+
final int dataCount = 64;
94+
final int parityCount = 64;
95+
final int shardSize = 200;
96+
byte [] [] dataShards = new byte [dataCount] [shardSize];
97+
for (byte [] shard : dataShards) {
98+
for (int i = 0; i < shard.length; i++) {
99+
shard[i] = (byte) random.nextInt(256);
100+
}
101+
}
102+
runEncodeDecode(dataCount, parityCount, dataShards);
85103
}
86104

87105
/**
@@ -90,35 +108,36 @@ public void testSimpleEncodeDecode() {
90108
*
91109
* Uses 5+5 coding, so there must be 5 input data shards.
92110
*/
93-
private void runEncodeDecode(byte[][] dataShards) {
111+
private void runEncodeDecode(int dataCount, int parityCount, byte[][] dataShards) {
94112

113+
final int totalCount = dataCount + parityCount;
95114
final int shardLength = dataShards[0].length;
96115

97116
// Make the list of data and parity shards.
98-
assertEquals(5, dataShards.length);
117+
assertEquals(dataCount, dataShards.length);
99118
final int dataLength = dataShards[0].length;
100-
byte [] [] allShards = new byte [10] [];
101-
for (int i = 0; i < 5; i++) {
119+
byte [] [] allShards = new byte [totalCount] [];
120+
for (int i = 0; i < dataCount; i++) {
102121
allShards[i] = Arrays.copyOf(dataShards[i], dataLength);
103122
}
104-
for (int i = 5; i < 10; i++) {
123+
for (int i = dataCount; i < totalCount; i++) {
105124
allShards[i] = new byte [dataLength];
106125
}
107126

108127
// Encode.
109-
ReedSolomon codec = ReedSolomon.create(5, 5);
128+
ReedSolomon codec = ReedSolomon.create(dataCount, parityCount);
110129
codec.encodeParity(allShards, 0, dataLength);
111130

112131
// Make a copy to decode with.
113-
byte [] [] testShards = new byte [10] [];
114-
boolean [] shardPresent = new boolean [10];
115-
for (int i = 0; i < 10; i++) {
132+
byte [] [] testShards = new byte [totalCount] [];
133+
boolean [] shardPresent = new boolean [totalCount];
134+
for (int i = 0; i < totalCount; i++) {
116135
testShards[i] = Arrays.copyOf(allShards[i], shardLength);
117136
shardPresent[i] = true;
118137
}
119138

120139
// Decode with 0, 1, ..., 5 shards missing.
121-
for (int numberMissing = 0; numberMissing < 6; numberMissing++) {
140+
for (int numberMissing = 0; numberMissing < parityCount + 1; numberMissing++) {
122141
tryAllSubsetsMissing(codec, allShards, testShards, shardPresent, numberMissing);
123142
}
124143
}

0 commit comments

Comments
 (0)