From c94b6f365ce47b35ca2af21c96f9e16823918658 Mon Sep 17 00:00:00 2001 From: Matthew Bloch Date: Sun, 20 May 2012 14:38:46 +0100 Subject: [PATCH] Tweaks to bitset.h, established a C test framework. --- Rakefile | 35 ++++++++++++++++++--- bitset.h | 74 ++++++++++++++++++++++++++++++++++++++++++++ tests/check_bitset.c | 57 ++++++++++++++++++++++++++++++++++ util.h | 1 + 4 files changed, 162 insertions(+), 5 deletions(-) create mode 100644 tests/check_bitset.c diff --git a/Rakefile b/Rakefile index bc7a965..b956ac6 100644 --- a/Rakefile +++ b/Rakefile @@ -5,6 +5,9 @@ OBJECTS = SOURCES.map { |s| "#{s}.o" } LIBS = %w( pthread ) CCFLAGS = %w( -Wall ) LDFLAGS = [] +LIBCHECK = "/usr/lib/libcheck.a" + +TEST_MODULES = Dir["tests/check_*.c"].map { |n| n[12..-3] } if DEBUG LDFLAGS << ["-g"] @@ -14,17 +17,39 @@ end rule 'default' => 'flexnbd' -rule 'flexnbd' => OBJECTS do |t| +namespace "test" do + task 'build' => TEST_MODULES.map { |n| "tests/check_#{n}" } + task 'run' => 'build' do + TEST_MODULES.each do |n| + ENV['EF_DISABLE_BANNER'] = '1' + sh "./tests/check_#{n}" + end + end +end + +def gcc_link(target, objects) sh "gcc #{LDFLAGS.join(' ')} "+ LIBS.map { |l| "-l#{l}" }.join(" ")+ - " -o #{t.name} "+ - t.sources.join(" ") + " -o #{target} "+ + objects.join(" ") +end + +rule 'flexnbd' => OBJECTS do |t| + gcc_link(t.name, t.sources) +end + +rule(/tests\/check_[a-z]+$/ => [ proc { |target| target+".o" } ]) do |t| + gcc_link(t.name, t.sources + [LIBCHECK]) end rule '.o' => '.c' do |t| - sh "gcc -c #{CCFLAGS.join(' ')} -o #{t.name} #{t.source} " + sh "gcc -I. -c #{CCFLAGS.join(' ')} -o #{t.name} #{t.source} " end rule 'clean' do - sh "rm -f flexnbd "+OBJECTS.join(" ") + sh "rm -f flexnbd " + ( + OBJECTS + + TEST_MODULES.map { |n| ["tests/check_#{n}", "tests/check_#{n}.o"] }.flatten + ). + join(" ") end diff --git a/bitset.h b/bitset.h index dc34fb4..51036a0 100644 --- a/bitset.h +++ b/bitset.h @@ -3,6 +3,9 @@ #include #include +#include + +#include "util.h" static inline char char_with_bit_set(int num) { return 1<<(num%8); } @@ -20,9 +23,11 @@ static inline int bit_has_value(char* b, int idx, int value) { } static inline void bit_set(char* b, int idx) { b[idx/8] |= char_with_bit_set(idx); + //__sync_fetch_and_or(b+(idx/8), char_with_bit_set(idx)); } static inline void bit_clear(char* b, int idx) { b[idx/8] &= ~char_with_bit_set(idx); + //__sync_fetch_and_nand(b+(idx/8), char_with_bit_set(idx)); } static inline void bit_set_range(char* b, int from, int len) { for (; from%8 != 0 && len > 0; len--) @@ -67,5 +72,74 @@ static inline int bit_run_count(char* b, int from, int len) { return count; } +struct bitset_mapping { + uint64_t size; + int resolution; + char bits[]; +}; + +static inline struct bitset_mapping* bitset_alloc( + uint64_t size, + int resolution +) +{ + struct bitset_mapping *bitset = xmalloc( + sizeof(struct bitset_mapping)+ + (size+resolution-1)/resolution + ); + bitset->size = size; + bitset->resolution = resolution; + return bitset; +} + +#define INT_FIRST_AND_LAST \ + int first = from/set->resolution, \ + last = (from+len-1)/set->resolution, \ + bitlen = last-first+1 + +static inline void bitset_set_range( + struct bitset_mapping* set, + uint64_t from, + uint64_t len) +{ + INT_FIRST_AND_LAST; + bit_set_range(set->bits, first, bitlen); +} + +static inline void bitset_clear_range( + struct bitset_mapping* set, + uint64_t from, + uint64_t len) +{ + INT_FIRST_AND_LAST; + bit_clear_range(set->bits, first, bitlen); +} + +static inline int bitset_run_count( + struct bitset_mapping* set, + uint64_t from, + uint64_t len) +{ + INT_FIRST_AND_LAST; + return bit_run_count(set->bits, first, bitlen) * set->resolution; +} + +static inline int bitset_is_clear_at( + struct bitset_mapping* set, + uint64_t at +) +{ + return bit_is_clear(set->bits, at/set->resolution); +} + +static inline int bitset_is_set_at( + struct bitset_mapping* set, + uint64_t at +) +{ + return bit_is_set(set->bits, at/set->resolution); +} + + #endif diff --git a/tests/check_bitset.c b/tests/check_bitset.c new file mode 100644 index 0000000..8c72c27 --- /dev/null +++ b/tests/check_bitset.c @@ -0,0 +1,57 @@ +#include + +#include "bitset.h" + +START_TEST(test_bit_set) +{ + unsigned char num; + char *bits = (char*) # + +#define TEST_BIT_SET(bit, newvalue) \ + bit_set(bits, (bit)); \ + fail_unless(num == (newvalue), "num was %x instead of %x", num, (newvalue)); + + TEST_BIT_SET(0, 1); + TEST_BIT_SET(1, 3); + TEST_BIT_SET(2, 7); + TEST_BIT_SET(7, 0x87); +} +END_TEST + +START_TEST(test_bit_clear) +{ + unsigned char num = 255; + char *bits = (char*) # + +#define TEST_BIT_CLEAR(bit, newvalue) \ + bit_clear(bits, (bit)); \ + fail_unless(num == (newvalue), "num was %x instead of %x", num, (newvalue)); + + TEST_BIT_CLEAR(0, 0xfe); + TEST_BIT_CLEAR(1, 0xfc); + TEST_BIT_CLEAR(2, 0xf8); + TEST_BIT_CLEAR(7, 0x78); +} +END_TEST + +Suite* bitset_suite() +{ + Suite *s = suite_create("bitset"); + TCase *tc_core = tcase_create("bitset"); + tcase_add_test(tc_core, test_bit_set); + tcase_add_test(tc_core, test_bit_clear); + suite_add_tcase(s, tc_core); + + return s; +} + +int main(void) +{ + int number_failed; + Suite *s = bitset_suite(); + SRunner *sr = srunner_create(s); + srunner_run_all(sr, CK_NORMAL); + number_failed = srunner_ntests_failed(sr); + srunner_free(sr); + return (number_failed == 0) ? 0 : 1; +} diff --git a/util.h b/util.h index b01f633..e1c5888 100644 --- a/util.h +++ b/util.h @@ -24,6 +24,7 @@ void* xmalloc(size_t size); error(0, client->socket, msg, ##__VA_ARGS__) #define CLIENT_ERROR_ON_FAILURE(test, msg, ...) \ if (test < 0) { error(1, client->socket, msg, ##__VA_ARGS__); } + #define SERVER_ERROR(msg, ...) \ error(0, 0, msg, ##__VA_ARGS__) #define SERVER_ERROR_ON_FAILURE(test, msg, ...) \