//////////////////////////////////////////////////////////////////////////////// // // This is a test program for Safe-Bit-Fields in the Loki Library. // Copyright (c) 2009 by Fedor Pikus & Rich Sposato // The copyright on this file is protected under the terms of the MIT license. // // Permission to use, copy, modify, distribute and sell this software for any // purpose is hereby granted without fee, provided that the above copyright // notice appear in all copies and that both that copyright notice and this // permission notice appear in supporting documentation. // The author makes no claims about the suitability of this software for any // purpose. It is provided "as is" without express or implied warranty. //////////////////////////////////////////////////////////////////////////////// // $Id$ #include #include using namespace std; using namespace Loki; LOKI_BIT_FIELD( unsigned int ) Cat_state; LOKI_BIT_CONST( Cat_state, CAT_NO_STATE, 0 ); // 0x0000 - no bit is set LOKI_BIT_CONST( Cat_state, CAT_SLEEPING, 1 ); // 0x0001 - 1st bit is set LOKI_BIT_CONST( Cat_state, CAT_PURRING, 2 ); // 0x0002 - 2nd bit is set LOKI_BIT_CONST( Cat_state, CAT_PLAYING, 3 ); // 0x0004 - 3rd bit is set LOKI_BIT_FIELD( unsigned int ) Dog_state; LOKI_BIT_CONST( Dog_state, DOG_BARKING, 1 ); LOKI_BIT_CONST( Dog_state, DOG_CHEWING, 2 ); LOKI_BIT_CONST( Dog_state, DOG_DROOLING, 3 ); LOKI_BIT_CONST( Dog_state, DOG_SLEEPING, 4 ); LOKI_BIT_CONST( Dog_state, DOG_GROWLING, 5 ); LOKI_BIT_CONST( Dog_state, DOG_TIRED, 6 ); LOKI_BIT_CONST( Dog_state, DOG_DEAD, 7 ); LOKI_BIT_CONST( Dog_state, DOG_GROWING, 8 ); LOKI_BIT_CONST( Dog_state, DOG_THINKING, 9 ); LOKI_BIT_CONST( Dog_state, DOG_YELPING, 10 ); LOKI_BIT_CONST( Dog_state, DOG_QUIET, 11 ); LOKI_BIT_CONST( Dog_state, DOG_FETCHING, 12 ); LOKI_BIT_CONST( Dog_state, DOG_HOWLING, 13 ); LOKI_BIT_CONST( Dog_state, DOG_SICK, 14 ); LOKI_BIT_CONST( Dog_state, DOG_JUMPING, 15 ); LOKI_BIT_CONST( Dog_state, DOG_SWIMMING, 16 ); LOKI_BIT_CONST( Dog_state, DOG_BATHING, 17 ); LOKI_BIT_CONST( Dog_state, DOG_EATING, 18 ); LOKI_BIT_CONST( Dog_state, DOG_DRINKING, 19 ); LOKI_BIT_CONST( Dog_state, DOG_PLAYING, 20 ); LOKI_BIT_CONST( Dog_state, DOG_RUNNING, 21 ); LOKI_BIT_CONST( Dog_state, DOG_BITING, 22 ); LOKI_BIT_CONST( Dog_state, DOG_BEGGING, 23 ); LOKI_BIT_CONST( Dog_state, DOG_WHINING, 24 ); LOKI_BIT_CONST( Dog_state, DOG_WALKING, 25 ); LOKI_BIT_CONST( Dog_state, DOG_SINGING, 26 ); LOKI_BIT_CONST( Dog_state, DOG_FIGHTING, 27 ); LOKI_BIT_CONST( Dog_state, DOG_MATING, 28 ); LOKI_BIT_CONST( Dog_state, DOG_FEEDING, 29 ); LOKI_BIT_CONST( Dog_state, DOG_BIRTHING, 30 ); LOKI_BIT_CONST( Dog_state, DOG_SHEDDING, 31 ); LOKI_BIT_CONST( Dog_state, DOG_TALKING, 32 ); #ifdef ERROR0 LOKI_BIT_CONST( Dog_state, DOG_TALKING, 20 ); // Can't have two values with same name. LOKI_BIT_CONST( Dog_state, DOG_BLOGGING, 33 ); // Can't set bit 33 in a 32 bit-sized object. #endif int main( void ) { cout << "Running tests on Loki safe bit fields." << endl; Cat_state cat_state = CAT_SLEEPING; assert( cat_state ); Dog_state dog_now; Dog_state dog_state = DOG_DROOLING; assert( dog_state ); bool happy = cat_state & ( CAT_SLEEPING | CAT_PURRING ); // OK assert( happy ); assert( CAT_SLEEPING < CAT_PURRING ); assert( CAT_SLEEPING <= CAT_SLEEPING ); assert( CAT_SLEEPING <= CAT_PURRING ); assert( CAT_SLEEPING != CAT_PURRING ); assert( CAT_SLEEPING == CAT_SLEEPING ); assert( CAT_PURRING >= CAT_SLEEPING ); assert( CAT_PURRING >= CAT_PURRING ); #ifdef ERROR1 assert( DOG_DROOLING != CAT_SLEEPING ); // Can't compare different types. #endif #ifdef ERROR2 if ( cat_state & DOG_BARKING ) {} // Wrong bit type #endif #ifdef ERROR3 if ( cat_state & CAT_SLEEPING == 0 ) {} // Operator precedence #endif #ifdef ERROR4 if ( dog_state && DOG_BARKING ) {} // Logical && #endif if ( dog_state & DOG_BARKING ) {} // OK #ifdef ERROR5 Cat_state state0 = 0; // Conversion from non-safe bits #endif Cat_state state = CAT_NO_STATE; // OK assert( !state ); state = ~state; assert( state ); assert( state != CAT_NO_STATE ); assert( state & CAT_SLEEPING ); assert( state & CAT_PURRING ); assert( state & CAT_PLAYING ); state = CAT_SLEEPING; assert( state == cat_state ); assert( state.size() == ( 8 * sizeof(unsigned int) ) ); assert( sizeof(Cat_state) == sizeof(unsigned int) ); dog_now = dog_state = DOG_BARKING; assert( dog_now == dog_state ); #ifdef ERROR6 if ( dog_state == cat_state ) {} // Don't allow comparison of different types. #endif /// @note All These assertions are inside #ifdef sections because they /// compare either SafeBitField or SafeBitConst to literal integers. /// If you compile any of these assertions they should generate errors. /// These #ifdef sections exhaustively demonstrate that all possible /// operations and comparisons with literal values are forbidden. #ifdef ERROR7 assert( dog_state == 1 ); // Don't allow comparisons to integers. #endif #ifdef ERROR8 assert( dog_state != 2 ); // Don't allow comparisons to integers. #endif #ifdef ERROR9 assert( dog_state < 2 ); // Don't allow comparisons to integers. #endif #ifdef ERROR10 assert( dog_state > 0 ); // Don't allow comparisons to integers. #endif #ifdef ERROR11 assert( dog_state <= 1 ); // Don't allow comparisons to integers. #endif #ifdef ERROR12 assert( dog_state >= 1 ); // Don't allow comparisons to integers. #endif #ifdef ERROR13 assert( DOG_BARKING == 1 ); // Don't allow comparisons to integers. #endif #ifdef ERROR14 assert( DOG_BARKING != 2 ); // Don't allow comparisons to integers. #endif #ifdef ERROR15 assert( DOG_BARKING < 2 ); // Don't allow comparisons to integers. #endif #ifdef ERROR16 assert( DOG_BARKING > 0 ); // Don't allow comparisons to integers. #endif #ifdef ERROR17 assert( DOG_BARKING <= 1 ); // Don't allow comparisons to integers. #endif #ifdef ERROR18 assert( DOG_BARKING >= 1 ); // Don't allow comparisons to integers. #endif #ifdef ERROR19 assert( ( dog_state | 1 ) != 0 ); // Don't allow operations with integers. #endif #ifdef ERROR20 assert( ( dog_state & 2 ) == 0 ); // Don't allow operations with integers. #endif #ifdef ERROR21 assert( ( dog_state ^ 1 ) == 0 ); // Don't allow operations with integers. #endif #ifdef ERROR22 assert( ( dog_state |= 2 ) == 3 ); // Don't allow operations with integers. #endif #ifdef ERROR23 assert( ( dog_state &= 3 ) == 2 ); // Don't allow operations with integers. #endif #ifdef ERROR24 assert( ( dog_state ^= 1 ) == 0 ); // Don't allow operations with integers. #endif #ifdef ERROR25 assert( ( DOG_BARKING | 1 ) != 0 ); // Don't allow operations with integers. #endif #ifdef ERROR26 assert( ( DOG_BARKING & 2 ) == 0 ); // Don't allow operations with integers. #endif #ifdef ERROR27 assert( ( DOG_BARKING ^ 1 ) == 0 ); // Don't allow operations with integers. #endif #ifdef ERROR28 assert( ( DOG_BARKING |= 2 ) == 3 ); // Don't allow operations with integers. #endif #ifdef ERROR29 assert( ( DOG_BARKING &= 3 ) == 2 ); // Don't allow operations with integers. #endif #ifdef ERROR30 assert( ( DOG_BARKING ^= 1 ) == 0 ); // Don't allow operations with integers. #endif /// @note All These assertions are inside #ifdef sections because they /// compare either SafeBitField or SafeBitConst to an int variable. /// If you compile any of these assertions they should generate errors. /// These #ifdef sections exhaustively demonstrate that all possible /// operations and comparisons with integers are forbidden. int value = 1; (void)value; #ifdef ERROR31 assert( dog_state == value ); // Don't allow comparisons to integers. #endif #ifdef ERROR32 value = 2; assert( dog_state != value ); // Don't allow comparisons to integers. #endif #ifdef ERROR33 value = 2; assert( dog_state < value ); // Don't allow comparisons to integers. #endif #ifdef ERROR34 value = 0; assert( dog_state > value ); // Don't allow comparisons to integers. #endif #ifdef ERROR35 value = 1; assert( dog_state <= value ); // Don't allow comparisons to integers. #endif #ifdef ERROR36 value = 1; assert( dog_state >= value ); // Don't allow comparisons to integers. #endif #ifdef ERROR37 value = 1; assert( DOG_BARKING == value ); // Don't allow comparisons to integers. #endif #ifdef ERROR38 value = 2; assert( DOG_BARKING != value ); // Don't allow comparisons to integers. #endif #ifdef ERROR39 value = 2; assert( DOG_BARKING < value ); // Don't allow comparisons to integers. #endif #ifdef ERROR40 value = 0; assert( DOG_BARKING > value ); // Don't allow comparisons to integers. #endif #ifdef ERROR41 value = 1; assert( DOG_BARKING <= value ); // Don't allow comparisons to integers. #endif #ifdef ERROR42 value = 1; assert( DOG_BARKING >= value ); // Don't allow comparisons to integers. #endif #ifdef ERROR43 value = 1; assert( ( dog_state | value ) != 0 ); // Don't allow operations with integers. #endif #ifdef ERROR44 value = 2; assert( ( dog_state & value ) == 0 ); // Don't allow operations with integers. #endif #ifdef ERROR45 value = 1; assert( ( dog_state ^ value ) == 0 ); // Don't allow operations with integers. #endif #ifdef ERROR46 value = 2; assert( ( dog_state |= value ) == 3 ); // Don't allow operations with integers. #endif #ifdef ERROR47 value = 3; assert( ( dog_state &= value ) == 2 ); // Don't allow operations with integers. #endif #ifdef ERROR48 value = 1; assert( ( dog_state ^= value ) == 0 ); // Don't allow operations with integers. #endif #ifdef ERROR49 value = 1; assert( ( DOG_BARKING | value ) != 0 ); // Don't allow operations with integers. #endif #ifdef ERROR50 value = 2; assert( ( DOG_BARKING & value ) == 0 ); // Don't allow operations with integers. #endif #ifdef ERROR51 value = 1; assert( ( DOG_BARKING ^ value ) == 0 ); // Don't allow operations with integers. #endif #ifdef ERROR52 value = 2; assert( ( DOG_BARKING |= value ) == 3 ); // Don't allow operations with integers. #endif #ifdef ERROR53 value = 3; assert( ( DOG_BARKING &= value ) == 2 ); // Don't allow operations with integers. #endif #ifdef ERROR54 value = 1; assert( ( DOG_BARKING ^= value ) == 0 ); // Don't allow operations with integers. #endif dog_now = dog_state |= DOG_CHEWING; assert( dog_state & ( DOG_CHEWING | DOG_BARKING ) ); assert( dog_now == dog_state ); dog_now = dog_state &= DOG_CHEWING; assert( dog_state == DOG_CHEWING ); assert( dog_now == dog_state ); dog_state = ~dog_state; assert( dog_state != DOG_CHEWING ); dog_state = ~dog_state; assert( dog_state == DOG_CHEWING ); cout << "If nothing asserted, then all tests passed!" << endl; return 0; }