Skip to content

Commit 0cf6874

Browse files
Utkarsh Mehtautkmehta
authored andcommitted
RUST-413 Implementing ObjectId spec tests
1 parent 6ae76f8 commit 0cf6874

File tree

2 files changed

+39
-12
lines changed

2 files changed

+39
-12
lines changed

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,12 +36,12 @@ hex = "0.4.2"
3636
md5 = "0.7.0"
3737
decimal = { version = "2.0.4", default_features = false, optional = true }
3838
base64 = "0.12.1"
39+
lazy_static = "1.4.0"
3940

4041
[dev-dependencies]
4142
assert_matches = "1.2"
4243
serde_bytes = "0.11"
4344
pretty_assertions = "0.6.1"
44-
lazy_static = "1.4.0"
4545

4646
[package.metadata.docs.rs]
4747
features = ["decimal128"]

src/oid.rs

Lines changed: 38 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ use hex::{self, FromHexError};
1616
use rand::{thread_rng, Rng};
1717

1818
use chrono::Utc;
19+
use lazy_static::lazy_static;
1920

2021
const TIMESTAMP_SIZE: usize = 4;
2122
const PROCESS_ID_SIZE: usize = 5;
@@ -27,7 +28,9 @@ const COUNTER_OFFSET: usize = PROCESS_ID_OFFSET + PROCESS_ID_SIZE;
2728

2829
const MAX_U24: usize = 0xFF_FFFF;
2930

30-
static OID_COUNTER: AtomicUsize = AtomicUsize::new(0);
31+
lazy_static! {
32+
static ref OID_COUNTER: AtomicUsize = AtomicUsize::new(thread_rng().gen_range(0, MAX_U24 + 1));
33+
}
3134

3235
/// Errors that can occur during OID construction and generation.
3336
#[derive(Debug)]
@@ -162,19 +165,10 @@ impl ObjectId {
162165
// Gets an incremental 3-byte count.
163166
// Represented in Big Endian.
164167
fn gen_count() -> [u8; 3] {
165-
// Init oid counter
166-
if OID_COUNTER.load(Ordering::SeqCst) == 0 {
167-
let start = thread_rng().gen_range(0, MAX_U24 + 1);
168-
OID_COUNTER.store(start, Ordering::SeqCst);
169-
}
170-
171168
let u_counter = OID_COUNTER.fetch_add(1, Ordering::SeqCst);
172169

173170
// Mod result instead of OID_COUNTER to prevent threading issues.
174-
// Static mutexes are currently unstable; once they have been
175-
// stabilized, one should be used to access OID_COUNTER and
176-
// perform multiple operations atomically.
177-
let u = u_counter % MAX_U24;
171+
let u = u_counter % (MAX_U24 + 1);
178172

179173
// Convert usize to writable u64, then extract the first three bytes.
180174
let u_int = u as u64;
@@ -224,6 +218,39 @@ fn count_generated_is_big_endian() {
224218
assert_eq!(0x33u8, oid.bytes()[COUNTER_OFFSET + 2]);
225219
}
226220

221+
#[test]
222+
fn test_counter_overflow_u24_max() {
223+
let _guard = LOCK.run_exclusively();
224+
let start = MAX_U24;
225+
OID_COUNTER.store(start, Ordering::SeqCst);
226+
let oid = ObjectId::new();
227+
assert_eq!(0xFFu8, oid.bytes()[COUNTER_OFFSET]);
228+
assert_eq!(0xFFu8, oid.bytes()[COUNTER_OFFSET + 1]);
229+
assert_eq!(0xFFu8, oid.bytes()[COUNTER_OFFSET + 2]);
230+
// Test counter overflows to 0 when set to MAX_24 + 1
231+
let oid_new = ObjectId::new();
232+
assert_eq!(0x00u8, oid_new.bytes()[COUNTER_OFFSET]);
233+
assert_eq!(0x00u8, oid_new.bytes()[COUNTER_OFFSET + 1]);
234+
assert_eq!(0x00u8, oid_new.bytes()[COUNTER_OFFSET + 2]);
235+
}
236+
237+
#[test]
238+
fn test_counter_overflow_usize_max() {
239+
let _guard = LOCK.run_exclusively();
240+
let start = usize::max_value();
241+
OID_COUNTER.store(start, Ordering::SeqCst);
242+
// Test counter overflows to u24_max when set to usize_max
243+
let oid = ObjectId::new();
244+
assert_eq!(0xFFu8, oid.bytes()[COUNTER_OFFSET]);
245+
assert_eq!(0xFFu8, oid.bytes()[COUNTER_OFFSET + 1]);
246+
assert_eq!(0xFFu8, oid.bytes()[COUNTER_OFFSET + 2]);
247+
// Test counter overflows to 0 when set to usize_max + 1
248+
let oid_new = ObjectId::new();
249+
assert_eq!(0x00u8, oid_new.bytes()[COUNTER_OFFSET]);
250+
assert_eq!(0x00u8, oid_new.bytes()[COUNTER_OFFSET + 1]);
251+
assert_eq!(0x00u8, oid_new.bytes()[COUNTER_OFFSET + 2]);
252+
}
253+
227254
#[cfg(test)]
228255
mod test {
229256
use chrono::{offset::TimeZone, Utc};

0 commit comments

Comments
 (0)