Skip to content

Commit 0e817e6

Browse files
adpaco-awstedinski
authored andcommitted
Add a test for ctpop (rust-lang#1048)
* Add a test for `ctpop` * Fix format
1 parent be24716 commit 0e817e6

File tree

1 file changed

+73
-0
lines changed

1 file changed

+73
-0
lines changed

tests/kani/Intrinsics/Count/ctpop.rs

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2+
// SPDX-License-Identifier: Apache-2.0 OR MIT
3+
4+
// Check that `ctpop` is supported and returns the expected results
5+
// (the number of bits equal to one in a value)
6+
#![feature(core_intrinsics)]
7+
use std::intrinsics::ctpop;
8+
9+
// Define a function for counting like `ctpop` and assert that their results are
10+
// the same for any value
11+
macro_rules! test_ctpop {
12+
( $fn_name:ident, $ty:ty ) => {
13+
fn $fn_name(x: $ty) -> $ty {
14+
let mut count = 0;
15+
let num_bits = <$ty>::BITS;
16+
for i in 0..num_bits {
17+
// Get value at index `i`
18+
let bitmask = 1 << i;
19+
let bit = x & bitmask;
20+
if bit != 0 {
21+
count += 1;
22+
}
23+
// The assertion below mitigates a low performance issue in this
24+
// test due to the loop having a conditional jump at the end,
25+
// see https://github.com/model-checking/kani/issues/1046 for
26+
// more details.
27+
assert!(count >= 0);
28+
}
29+
count
30+
}
31+
let var: $ty = kani::any();
32+
// Check that the result is correct
33+
assert!($fn_name(var) == ctpop(var));
34+
35+
// Check that the stable version returns the same value
36+
assert!(ctpop(var) as u32 == var.count_ones());
37+
};
38+
}
39+
40+
#[kani::proof]
41+
fn test_ctpop_u8() {
42+
test_ctpop!(my_ctpop_u8, u8);
43+
}
44+
45+
#[kani::proof]
46+
fn test_ctpop_u16() {
47+
test_ctpop!(my_ctpop_u16, u16);
48+
}
49+
50+
#[kani::proof]
51+
fn test_ctpop_u32() {
52+
test_ctpop!(my_ctpop_u32, u32);
53+
}
54+
55+
#[kani::proof]
56+
fn test_ctpop_u64() {
57+
test_ctpop!(my_ctpop_u64, u64);
58+
}
59+
60+
// We do not run the test for u128 because it takes too long
61+
fn test_ctpop_u128() {
62+
test_ctpop!(my_ctpop_u128, u128);
63+
}
64+
65+
#[kani::proof]
66+
fn test_ctpop_usize() {
67+
test_ctpop!(my_ctpop_usize, usize);
68+
}
69+
70+
// `ctpop` also works with signed integer types, but this causes overflows
71+
// unless we restrict their values considerably (due to the conversions in
72+
// `count_ones`), making the signed versions not very interesting to test here.
73+
// https://github.com/model-checking/kani/issues/934

0 commit comments

Comments
 (0)