 acf85eb9ab
			
		
	
	acf85eb9ab
	
	
	
		
			
			* Speedups: remove dependency on c++ * Speedups: intset: handle malloc failing * Speedups: intset: fix corner case for int64 on 32bit systems original idea was to only use bucket->val if int<pointer, but we always have a union now anyway * Speedups: add size comment to player_set bucket configuration * test: more tests for LocationStore.find_item * test: require _speedups in CI This kind of tests that the build succeeds. * test: even more tests for LocationStore.find_item * Speedups: intset uniform comment style * Speedups: intset: avoid memory leak when realloc fails * Speedups: intset: make `gcc -pedantic -std=c99 -fanalyzer` without warnings Unnamed unions are not in C99, this got fixed. The overhead of setting count=0 is minimal or optimized-out and silences -fanalizer (see comment). * Speedups: don't leak memory in case of exception * Speedups: intset: validate alloc and free This won't happen in our cython, but it's still a good addition. * CI: add test framework for C/C++ code * CI: ctest: fix cwd * Speedups: intset: ignore msvc warning * Tests: intset: revert attempt at no-asan We solve this with env vars in ctest now, and this fails for msvc. * Test: cpp: docs: fix typo * Test: cpp: docs: fix another typo * Test: intset: proper bucket count for Negative test INTxx_MIN % 1 would not produce a negative number, so the test was flawed.
		
			
				
	
	
		
			106 lines
		
	
	
		
			2.7 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			106 lines
		
	
	
		
			2.7 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| #include <limits>
 | |
| #include <cstdint>
 | |
| #include <gtest/gtest.h>
 | |
| 
 | |
| // uint32Set
 | |
| #define INTSET_NAME uint32Set
 | |
| #define INTSET_TYPE uint32_t
 | |
| #include "../../../intset.h"
 | |
| #undef INTSET_NAME
 | |
| #undef INTSET_TYPE
 | |
| 
 | |
| // int64Set
 | |
| #define INTSET_NAME int64Set
 | |
| #define INTSET_TYPE int64_t
 | |
| #include "../../../intset.h"
 | |
| 
 | |
| 
 | |
| TEST(IntsetTest, ZeroBuckets)
 | |
| {
 | |
|     // trying to allocate with zero buckets has to either fail or be functioning
 | |
|     uint32Set *set = uint32Set_new(0);
 | |
|     if (!set)
 | |
|         return; // failed -> OK
 | |
| 
 | |
|     EXPECT_FALSE(uint32Set_contains(set, 1));
 | |
|     EXPECT_TRUE(uint32Set_add(set, 1));
 | |
|     EXPECT_TRUE(uint32Set_contains(set, 1));
 | |
|     uint32Set_free(set);
 | |
| }
 | |
| 
 | |
| TEST(IntsetTest, Duplicate)
 | |
| {
 | |
|     // adding the same number again can't fail
 | |
|     uint32Set *set = uint32Set_new(2);
 | |
|     ASSERT_TRUE(set);
 | |
|     EXPECT_TRUE(uint32Set_add(set, 0));
 | |
|     EXPECT_TRUE(uint32Set_add(set, 0));
 | |
|     EXPECT_TRUE(uint32Set_contains(set, 0));
 | |
|     uint32Set_free(set);
 | |
| }
 | |
| 
 | |
| TEST(IntsetTest, SetAllocFailure)
 | |
| {
 | |
|     // try to allocate 100TB of RAM, should fail and return NULL
 | |
|     if (sizeof(size_t) < 8)
 | |
|         GTEST_SKIP() << "Alloc error not testable on 32bit";
 | |
|     int64Set *set = int64Set_new(6250000000000ULL);
 | |
|     EXPECT_FALSE(set);
 | |
|     int64Set_free(set);
 | |
| }
 | |
| 
 | |
| TEST(IntsetTest, SetAllocOverflow)
 | |
| {
 | |
|     // try to overflow argument passed to malloc
 | |
|     int64Set *set = int64Set_new(std::numeric_limits<size_t>::max());
 | |
|     EXPECT_FALSE(set);
 | |
|     int64Set_free(set);
 | |
| }
 | |
| 
 | |
| TEST(IntsetTest, NullFree)
 | |
| {
 | |
|     // free(NULL) should not try to free buckets
 | |
|     uint32Set_free(NULL);
 | |
|     int64Set_free(NULL);
 | |
| }
 | |
| 
 | |
| TEST(IntsetTest, BucketRealloc)
 | |
| {
 | |
|     // add a couple of values to the same bucket to test growing the bucket
 | |
|     uint32Set* set = uint32Set_new(1);
 | |
|     ASSERT_TRUE(set);
 | |
|     EXPECT_FALSE(uint32Set_contains(set, 0));
 | |
|     EXPECT_TRUE(uint32Set_add(set, 0));
 | |
|     EXPECT_TRUE(uint32Set_contains(set, 0));
 | |
|     for (uint32_t i = 1; i < 32; ++i) {
 | |
|         EXPECT_TRUE(uint32Set_add(set, i));
 | |
|         EXPECT_TRUE(uint32Set_contains(set, i - 1));
 | |
|         EXPECT_TRUE(uint32Set_contains(set, i));
 | |
|         EXPECT_FALSE(uint32Set_contains(set, i + 1));
 | |
|     }
 | |
|     uint32Set_free(set);
 | |
| }
 | |
| 
 | |
| TEST(IntSet, Max)
 | |
| {
 | |
|     constexpr auto n = std::numeric_limits<uint32_t>::max();
 | |
|     uint32Set *set = uint32Set_new(1);
 | |
|     ASSERT_TRUE(set);
 | |
|     EXPECT_FALSE(uint32Set_contains(set, n));
 | |
|     EXPECT_TRUE(uint32Set_add(set, n));
 | |
|     EXPECT_TRUE(uint32Set_contains(set, n));
 | |
|     uint32Set_free(set);
 | |
| }
 | |
| 
 | |
| TEST(InsetTest, Negative)
 | |
| {
 | |
|     constexpr auto n = std::numeric_limits<int64_t>::min();
 | |
|     static_assert(n < 0, "n not negative");
 | |
|     int64Set *set = int64Set_new(3);
 | |
|     ASSERT_TRUE(set);
 | |
|     EXPECT_FALSE(int64Set_contains(set, n));
 | |
|     EXPECT_TRUE(int64Set_add(set, n));
 | |
|     EXPECT_TRUE(int64Set_contains(set, n));
 | |
|     int64Set_free(set);
 | |
| }
 |