Skip to content

Commit 9237e27

Browse files
committed
Test with minimum and maximum seed values
Visual inspection of the 64-bit implementation while working on the 128-bit implementation showed a non-wrapping addition. In debug mode, this would panic, but thankfully release mode would wrap as desired. This enhances the property tests to ensure that seeds of all `0` bits and all `1` bits are explicitly tested.
1 parent 75f9e5f commit 9237e27

File tree

2 files changed

+35
-24
lines changed

2 files changed

+35
-24
lines changed

comparison/src/lib.rs

+31-23
Original file line numberDiff line numberDiff line change
@@ -13,37 +13,37 @@ mod xxhash32 {
1313

1414
proptest! {
1515
#[test]
16-
fn oneshot_same_as_one_chunk(seed: u32, data: Vec<u8>) {
16+
fn oneshot_same_as_one_chunk(seed in seed_32(), data: Vec<u8>) {
1717
oneshot_same_as_one_chunk_impl(seed, &data)?;
1818
}
1919

2020
#[test]
21-
fn oneshot_same_as_one_chunk_with_an_offset(seed: u32, (data, offset) in vec_and_index()) {
21+
fn oneshot_same_as_one_chunk_with_an_offset(seed in seed_32(), (data, offset) in vec_and_index()) {
2222
oneshot_same_as_one_chunk_impl(seed, &data[offset..])?;
2323
}
2424

2525
#[test]
26-
fn oneshot_same_as_many_chunks(seed: u32, (data, chunks) in data_and_chunks()) {
26+
fn oneshot_same_as_many_chunks(seed in seed_32(), (data, chunks) in data_and_chunks()) {
2727
oneshot_same_as_many_chunks_impl(seed, &data, &chunks)?;
2828
}
2929

3030
#[test]
31-
fn oneshot(seed: u32, data: Vec<u8>) {
31+
fn oneshot(seed in seed_32(), data: Vec<u8>) {
3232
oneshot_impl(seed, &data)?;
3333
}
3434

3535
#[test]
36-
fn oneshot_with_an_offset(seed: u32, (data, offset) in vec_and_index()) {
36+
fn oneshot_with_an_offset(seed in seed_32(), (data, offset) in vec_and_index()) {
3737
oneshot_impl(seed, &data[offset..])?;
3838
}
3939

4040
#[test]
41-
fn streaming_one_chunk(seed: u32, data: Vec<u8>) {
41+
fn streaming_one_chunk(seed in seed_32(), data: Vec<u8>) {
4242
streaming_one_chunk_impl(seed, &data)?;
4343
}
4444

4545
#[test]
46-
fn streaming_one_chunk_with_an_offset(seed: u32, (data, offset) in vec_and_index()) {
46+
fn streaming_one_chunk_with_an_offset(seed in seed_32(), (data, offset) in vec_and_index()) {
4747
streaming_one_chunk_impl(seed, &data[offset..])?;
4848
}
4949
}
@@ -112,37 +112,37 @@ mod xxhash64 {
112112

113113
proptest! {
114114
#[test]
115-
fn oneshot_same_as_one_chunk(seed: u64, data: Vec<u8>) {
115+
fn oneshot_same_as_one_chunk(seed in seed_64(), data: Vec<u8>) {
116116
oneshot_same_as_one_chunk_impl(seed, &data)?;
117117
}
118118

119119
#[test]
120-
fn oneshot_same_as_one_chunk_with_an_offset(seed: u64, (data, offset) in vec_and_index()) {
120+
fn oneshot_same_as_one_chunk_with_an_offset(seed in seed_64(), (data, offset) in vec_and_index()) {
121121
oneshot_same_as_one_chunk_impl(seed, &data[offset..])?;
122122
}
123123

124124
#[test]
125-
fn oneshot_same_as_many_chunks(seed: u64, (data, chunks) in data_and_chunks()) {
125+
fn oneshot_same_as_many_chunks(seed in seed_64(), (data, chunks) in data_and_chunks()) {
126126
oneshot_same_as_many_chunks_impl(seed, &data, &chunks)?;
127127
}
128128

129129
#[test]
130-
fn oneshot(seed: u64, data: Vec<u8>) {
130+
fn oneshot(seed in seed_64(), data: Vec<u8>) {
131131
oneshot_impl(seed, &data)?;
132132
}
133133

134134
#[test]
135-
fn oneshot_with_an_offset(seed: u64, (data, offset) in vec_and_index()) {
135+
fn oneshot_with_an_offset(seed in seed_64(), (data, offset) in vec_and_index()) {
136136
oneshot_impl(seed, &data[offset..])?;
137137
}
138138

139139
#[test]
140-
fn streaming_one_chunk(seed: u64, data: Vec<u8>) {
140+
fn streaming_one_chunk(seed in seed_64(), data: Vec<u8>) {
141141
streaming_one_chunk_impl(seed, &data)?;
142142
}
143143

144144
#[test]
145-
fn streaming_one_chunk_with_an_offset(seed: u64, (data, offset) in vec_and_index()) {
145+
fn streaming_one_chunk_with_an_offset(seed in seed_64(), (data, offset) in vec_and_index()) {
146146
streaming_one_chunk_impl(seed, &data[offset..])?;
147147
}
148148
}
@@ -212,27 +212,27 @@ mod xxhash3_64 {
212212

213213
proptest! {
214214
#[test]
215-
fn oneshot_same_as_one_chunk(seed: u64, data: Vec<u8>) {
215+
fn oneshot_same_as_one_chunk(seed in seed_64(), data: Vec<u8>) {
216216
oneshot_same_as_one_chunk_impl(seed, &data)?;
217217
}
218218

219219
#[test]
220-
fn oneshot_same_as_one_chunk_with_an_offset(seed: u64, (data, offset) in vec_and_index()) {
220+
fn oneshot_same_as_one_chunk_with_an_offset(seed in seed_64(), (data, offset) in vec_and_index()) {
221221
oneshot_same_as_one_chunk_impl(seed, &data[offset..])?;
222222
}
223223

224224
#[test]
225-
fn oneshot_same_as_many_chunks(seed: u64, (data, chunks) in data_and_chunks()) {
225+
fn oneshot_same_as_many_chunks(seed in seed_64(), (data, chunks) in data_and_chunks()) {
226226
oneshot_same_as_many_chunks_impl(seed, &data, &chunks)?;
227227
}
228228

229229
#[test]
230-
fn oneshot(seed: u64, data: Vec<u8>) {
230+
fn oneshot(seed in seed_64(), data: Vec<u8>) {
231231
oneshot_impl(seed, &data)?;
232232
}
233233

234234
#[test]
235-
fn oneshot_with_an_offset(seed: u64, (data, offset) in vec_and_index()) {
235+
fn oneshot_with_an_offset(seed in seed_64(), (data, offset) in vec_and_index()) {
236236
oneshot_impl(seed, &data[offset..])?;
237237
}
238238

@@ -242,22 +242,22 @@ mod xxhash3_64 {
242242
}
243243

244244
#[test]
245-
fn oneshot_with_a_seed_and_secret(seed: u64, secret in secret(), data: Vec<u8>) {
245+
fn oneshot_with_a_seed_and_secret(seed in seed_64(), secret in secret(), data: Vec<u8>) {
246246
oneshot_with_seed_and_secret_impl(seed, &secret, &data)?;
247247
}
248248

249249
#[test]
250-
fn streaming_one_chunk(seed: u64, data: Vec<u8>) {
250+
fn streaming_one_chunk(seed in seed_64(), data: Vec<u8>) {
251251
streaming_one_chunk_impl(seed, &data)?;
252252
}
253253

254254
#[test]
255-
fn streaming_one_chunk_with_an_offset(seed: u64, (data, offset) in vec_and_index()) {
255+
fn streaming_one_chunk_with_an_offset(seed in seed_64(), (data, offset) in vec_and_index()) {
256256
streaming_one_chunk_impl(seed, &data[offset..])?;
257257
}
258258

259259
#[test]
260-
fn streaming_with_a_seed_and_secret(seed: u64, secret in secret(), data: Vec<u8>) {
260+
fn streaming_with_a_seed_and_secret(seed in seed_64(), secret in secret(), data: Vec<u8>) {
261261
streaming_with_seed_and_secret_impl(seed, &secret, &data)?;
262262
}
263263
}
@@ -363,6 +363,14 @@ mod xxhash3_64 {
363363
}
364364
}
365365

366+
fn seed_32() -> impl Strategy<Value = u32> {
367+
prop_oneof![Just(0), Just(u32::MAX), num::u32::ANY]
368+
}
369+
370+
fn seed_64() -> impl Strategy<Value = u64> {
371+
prop_oneof![Just(0), Just(u64::MAX), num::u64::ANY]
372+
}
373+
366374
fn vec_and_index() -> impl Strategy<Value = (Vec<u8>, usize)> {
367375
prop::collection::vec(num::u8::ANY, 0..=32 * 1024).prop_flat_map(|vec| {
368376
let len = vec.len();

src/xxhash3_64.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -896,7 +896,10 @@ fn impl_1_to_3_bytes(secret: &Secret, seed: u64, input: &[u8]) -> u64 {
896896

897897
let secret_words = secret.words_for_1_to_3();
898898

899-
let value = ((secret_words[0] ^ secret_words[1]).into_u64() + seed) ^ combined.into_u64();
899+
let value = {
900+
let secret = (secret_words[0] ^ secret_words[1]).into_u64();
901+
secret.wrapping_add(seed) ^ combined.into_u64()
902+
};
900903

901904
// FUTURE: TEST: "Note that the XXH3-64 result is the lower half of XXH3-128 result."
902905
avalanche_xxh64(value)

0 commit comments

Comments
 (0)