trema 0.4.5 → 0.4.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile +4 -4
- data/Guardfile +8 -0
- data/Rakefile +2 -1
- data/bin/trema +4 -0
- data/cruise.rb +1 -1
- data/features/core/switch_manager.feature +2 -2
- data/features/examples/message.vendor-action.feature +2 -2
- data/features/examples/message.vendor-stats-request.feature +20 -0
- data/features/trema_commands/kill.feature +4 -0
- data/features/trema_commands/killall.feature +1 -0
- data/features/trema_commands/run.feature +20 -1
- data/ruby/trema/command/run.rb +4 -0
- data/ruby/trema/default_openflow_channel_port.rb +26 -0
- data/ruby/trema/dsl/configuration.rb +2 -1
- data/ruby/trema/open-vswitch.rb +2 -4
- data/ruby/trema/stats-reply.c +10 -1
- data/ruby/trema/stats-request.c +34 -1
- data/ruby/trema/vendor-stats-reply.rb +6 -2
- data/ruby/trema/version.rb +1 -1
- data/spec/trema/dsl/runner_spec.rb +1 -1
- data/spec/trema/dsl/syntax_spec.rb +1 -1
- data/spec/trema/shell/vswitch_spec.rb +1 -1
- data/spec/trema/stats-reply_spec.rb +2 -1
- data/spec/trema/stats-request_spec.rb +11 -0
- data/src/examples/cbench_switch/cbench-switch.rb +1 -0
- data/src/examples/cbench_switch/cbench_switch.c +1 -1
- data/src/examples/openflow_message/vendor-action.rb +4 -4
- data/src/examples/openflow_message/vendor-stats-request.rb +66 -0
- data/src/examples/simple_router/arp-table.rb +6 -17
- data/src/examples/simple_router/interface.rb +20 -29
- data/src/examples/simple_router/routing-table.rb +15 -22
- data/src/examples/simple_router/simple-router.rb +75 -64
- data/src/lib/chibach.c +3 -2
- data/src/lib/event_handler.c +55 -23
- data/src/lib/event_handler.h +0 -5
- data/src/lib/external_callback.c +126 -0
- data/src/lib/external_callback.h +46 -0
- data/src/lib/messenger.c +58 -35
- data/src/lib/openflow_message.c +32 -11
- data/src/lib/trema.c +13 -7
- data/src/lib/trema.h +1 -0
- data/src/lib/utility.c +13 -2
- data/src/switch_manager/secure_channel_receiver.c +6 -1
- data/src/switch_manager/switch.c +27 -26
- data/src/switch_manager/switch_manager.c +31 -10
- data/src/tremashark/packet_capture.c +3 -2
- data/src/tremashark/tremashark.c +2 -2
- data/trema.gemspec +1 -1
- data/unittests/lib/external_callback_test.c +282 -0
- data/unittests/lib/messenger_test.c +22 -0
- data/unittests/lib/openflow_message_test.c +1 -1
- data/unittests/lib/trema_test.c +1 -1
- data/unittests/switch_manager/switch_manager_test.c +3 -3
- metadata +12 -6
- data/src/examples/simple_router/router-utils.rb +0 -211
data/src/lib/openflow_message.c
CHANGED
@@ -1819,7 +1819,10 @@ validate_features_request( const buffer *message ) {
|
|
1819
1819
|
|
1820
1820
|
static int
|
1821
1821
|
validate_phy_port_no( const uint16_t port_no ) {
|
1822
|
-
if (
|
1822
|
+
if ( port_no == OFPP_LOCAL ) {
|
1823
|
+
return 0;
|
1824
|
+
}
|
1825
|
+
if ( ( port_no == 0 ) || ( port_no > OFPP_MAX ) ) {
|
1823
1826
|
return ERROR_INVALID_PORT_NO;
|
1824
1827
|
}
|
1825
1828
|
|
@@ -1827,6 +1830,26 @@ validate_phy_port_no( const uint16_t port_no ) {
|
|
1827
1830
|
}
|
1828
1831
|
|
1829
1832
|
|
1833
|
+
static int
|
1834
|
+
validate_in_port_no( const uint16_t port_no ) {
|
1835
|
+
if ( ( port_no == OFPP_CONTROLLER ) || ( port_no == OFPP_NONE ) ) {
|
1836
|
+
return 0;
|
1837
|
+
}
|
1838
|
+
|
1839
|
+
return validate_phy_port_no( port_no );
|
1840
|
+
}
|
1841
|
+
|
1842
|
+
|
1843
|
+
static int
|
1844
|
+
validate_out_port_no( const uint16_t port_no ) {
|
1845
|
+
if ( port_no >= OFPP_IN_PORT ) {
|
1846
|
+
return 0;
|
1847
|
+
}
|
1848
|
+
|
1849
|
+
return validate_phy_port_no( port_no );
|
1850
|
+
}
|
1851
|
+
|
1852
|
+
|
1830
1853
|
static int
|
1831
1854
|
validate_phy_port( struct ofp_phy_port *port ) {
|
1832
1855
|
int ret;
|
@@ -1990,7 +2013,7 @@ validate_packet_in( const buffer *message ) {
|
|
1990
2013
|
// packet_in->total_len
|
1991
2014
|
// packet_in->in_port
|
1992
2015
|
|
1993
|
-
ret =
|
2016
|
+
ret = validate_in_port_no( ntohs( packet_in->in_port ) );
|
1994
2017
|
if ( ret < 0 ) {
|
1995
2018
|
return ret;
|
1996
2019
|
}
|
@@ -2162,7 +2185,7 @@ validate_packet_out( const buffer *message ) {
|
|
2162
2185
|
|
2163
2186
|
packet_out = ( struct ofp_packet_out * ) message->data;
|
2164
2187
|
|
2165
|
-
ret =
|
2188
|
+
ret = validate_in_port_no( ntohs( packet_out->in_port ) );
|
2166
2189
|
if ( ret < 0 ) {
|
2167
2190
|
return ret;
|
2168
2191
|
}
|
@@ -2227,11 +2250,9 @@ validate_flow_mod( const buffer *message ) {
|
|
2227
2250
|
|
2228
2251
|
if ( ( ntohs( flow_mod->command ) == OFPFC_DELETE )
|
2229
2252
|
|| ( ntohs( flow_mod->command ) == OFPFC_DELETE_STRICT ) ) {
|
2230
|
-
|
2231
|
-
|
2232
|
-
|
2233
|
-
return ret;
|
2234
|
-
}
|
2253
|
+
ret = validate_out_port_no( ntohs( flow_mod->out_port ) );
|
2254
|
+
if ( ret < 0 ) {
|
2255
|
+
return ret;
|
2235
2256
|
}
|
2236
2257
|
}
|
2237
2258
|
|
@@ -2357,7 +2378,7 @@ validate_flow_stats_request( const buffer *message ) {
|
|
2357
2378
|
|
2358
2379
|
// flow_stats_request->table_id
|
2359
2380
|
|
2360
|
-
ret =
|
2381
|
+
ret = validate_out_port_no( ntohs( flow_stats_request->out_port ) );
|
2361
2382
|
if ( ret < 0 ) {
|
2362
2383
|
return ret;
|
2363
2384
|
}
|
@@ -2403,7 +2424,7 @@ validate_aggregate_stats_request( const buffer *message ) {
|
|
2403
2424
|
|
2404
2425
|
// aggregate_stats_request->table_id
|
2405
2426
|
|
2406
|
-
ret =
|
2427
|
+
ret = validate_out_port_no( ntohs( aggregate_stats_request->out_port ) );
|
2407
2428
|
if ( ret < 0 ) {
|
2408
2429
|
return ret;
|
2409
2430
|
}
|
@@ -3217,7 +3238,7 @@ validate_action_output( const struct ofp_action_output *action ) {
|
|
3217
3238
|
return ERROR_TOO_LONG_ACTION_OUTPUT;
|
3218
3239
|
}
|
3219
3240
|
|
3220
|
-
ret =
|
3241
|
+
ret = validate_out_port_no( output.port );
|
3221
3242
|
if ( ret < 0 ) {
|
3222
3243
|
return ret;
|
3223
3244
|
}
|
data/src/lib/trema.c
CHANGED
@@ -238,11 +238,11 @@ bool mock_init_timer();
|
|
238
238
|
#define finalize_timer mock_finalize_timer
|
239
239
|
bool mock_finalize_timer();
|
240
240
|
|
241
|
-
#ifdef
|
242
|
-
#undef
|
241
|
+
#ifdef push_external_callback
|
242
|
+
#undef push_external_callback
|
243
243
|
#endif
|
244
|
-
#define
|
245
|
-
bool
|
244
|
+
#define push_external_callback mock_push_external_callback
|
245
|
+
bool mock_push_external_callback( void ( *callback )( void ) );
|
246
246
|
|
247
247
|
#ifdef dump_stats
|
248
248
|
#undef dump_stats
|
@@ -506,12 +506,18 @@ ignore_sigpipe() {
|
|
506
506
|
}
|
507
507
|
|
508
508
|
|
509
|
+
static void
|
510
|
+
set_do_stop_trema_as_external_callback() {
|
511
|
+
push_external_callback( stop_trema );
|
512
|
+
}
|
513
|
+
|
514
|
+
|
509
515
|
static void
|
510
516
|
set_exit_handler() {
|
511
517
|
struct sigaction signal_exit;
|
512
518
|
|
513
519
|
memset( &signal_exit, 0, sizeof( struct sigaction ) );
|
514
|
-
signal_exit.sa_handler = ( void * )
|
520
|
+
signal_exit.sa_handler = ( void * ) set_do_stop_trema_as_external_callback;
|
515
521
|
sigaction( SIGINT, &signal_exit, NULL );
|
516
522
|
sigaction( SIGTERM, &signal_exit, NULL );
|
517
523
|
}
|
@@ -525,7 +531,7 @@ do_restart_log() {
|
|
525
531
|
|
526
532
|
static void
|
527
533
|
set_do_restart_log_as_external_callback() {
|
528
|
-
|
534
|
+
push_external_callback( do_restart_log );
|
529
535
|
}
|
530
536
|
|
531
537
|
|
@@ -541,7 +547,7 @@ set_hup_handler() {
|
|
541
547
|
|
542
548
|
static void
|
543
549
|
set_dump_stats_as_external_callback() {
|
544
|
-
|
550
|
+
push_external_callback( dump_stats );
|
545
551
|
}
|
546
552
|
|
547
553
|
|
data/src/lib/trema.h
CHANGED
data/src/lib/utility.c
CHANGED
@@ -68,8 +68,19 @@ hash_core( const void *key, int size ) {
|
|
68
68
|
const uint32_t prime = 0x01000193UL;
|
69
69
|
const unsigned char *c = key;
|
70
70
|
|
71
|
-
|
72
|
-
|
71
|
+
uint32_t value = 0;
|
72
|
+
int i = 0;
|
73
|
+
for ( ; ( i + ( int ) sizeof( uint32_t ) ) <= size; i += ( int ) sizeof( uint32_t ) ) {
|
74
|
+
memcpy( &value, &c[ i ], sizeof( uint32_t ) );
|
75
|
+
hash_value ^= value;
|
76
|
+
hash_value *= prime;
|
77
|
+
}
|
78
|
+
if ( i < size ) {
|
79
|
+
for ( ; i < size; i++ ) {
|
80
|
+
value <<= 8;
|
81
|
+
value |= ( ( uint32_t ) c[ i ] & 0xff );
|
82
|
+
}
|
83
|
+
hash_value ^= value;
|
73
84
|
hash_value *= prime;
|
74
85
|
}
|
75
86
|
|
@@ -53,7 +53,12 @@ recv_from_secure_channel( struct switch_info *sw_info ) {
|
|
53
53
|
if ( errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK ) {
|
54
54
|
return 0;
|
55
55
|
}
|
56
|
-
|
56
|
+
if ( errno == ECONNRESET ) {
|
57
|
+
debug( "Connection reset by peer." );
|
58
|
+
}
|
59
|
+
else {
|
60
|
+
error( "Receive error: %s(%d)", strerror( errno ), errno );
|
61
|
+
}
|
57
62
|
return -1;
|
58
63
|
}
|
59
64
|
if ( recv_length == 0 ) {
|
data/src/switch_manager/switch.c
CHANGED
@@ -526,6 +526,8 @@ confirm_self_dpid_is_registered( const list_element *switches, void *user_data )
|
|
526
526
|
if ( found ) {
|
527
527
|
sw_info->state = SWITCH_STATE_COMPLETED;
|
528
528
|
|
529
|
+
finalize_openflow_application_interface();
|
530
|
+
|
529
531
|
// notify state and datapath_id to controllers
|
530
532
|
service_send_state( sw_info, &sw_info->datapath_id, MESSENGER_OPENFLOW_READY );
|
531
533
|
debug( "send ready state" );
|
@@ -540,31 +542,31 @@ confirm_self_dpid_is_registered( const list_element *switches, void *user_data )
|
|
540
542
|
|
541
543
|
|
542
544
|
static void
|
543
|
-
stop_switch(
|
544
|
-
if (
|
545
|
-
close(
|
546
|
-
|
545
|
+
stop_switch() {
|
546
|
+
if ( switch_info.secure_channel_fd >= 0 ) {
|
547
|
+
close( switch_info.secure_channel_fd );
|
548
|
+
switch_info.secure_channel_fd = -1;
|
547
549
|
}
|
548
550
|
uint8_t state = MESSENGER_OPENFLOW_DISCONNECTED;
|
549
|
-
if (
|
551
|
+
if ( switch_info.state == SWITCH_STATE_CONNECTION_FAILED ) {
|
550
552
|
state = MESSENGER_OPENFLOW_FAILD_TO_CONNECT;
|
551
553
|
}
|
552
|
-
service_send_state(
|
554
|
+
service_send_state( &switch_info, &switch_info.datapath_id, state );
|
553
555
|
flush_messenger();
|
554
556
|
|
555
557
|
// free service name list
|
556
|
-
iterate_list(
|
557
|
-
delete_list(
|
558
|
-
|
559
|
-
iterate_list(
|
560
|
-
delete_list(
|
561
|
-
|
562
|
-
iterate_list(
|
563
|
-
delete_list(
|
564
|
-
|
565
|
-
iterate_list(
|
566
|
-
delete_list(
|
567
|
-
|
558
|
+
iterate_list( switch_info.vendor_service_name_list, xfree_data, NULL );
|
559
|
+
delete_list( switch_info.vendor_service_name_list );
|
560
|
+
switch_info.vendor_service_name_list = NULL;
|
561
|
+
iterate_list( switch_info.packetin_service_name_list, xfree_data, NULL );
|
562
|
+
delete_list( switch_info.packetin_service_name_list );
|
563
|
+
switch_info.packetin_service_name_list = NULL;
|
564
|
+
iterate_list( switch_info.portstatus_service_name_list, xfree_data, NULL );
|
565
|
+
delete_list( switch_info.portstatus_service_name_list );
|
566
|
+
switch_info.portstatus_service_name_list = NULL;
|
567
|
+
iterate_list( switch_info.state_service_name_list, xfree_data, NULL );
|
568
|
+
delete_list( switch_info.state_service_name_list );
|
569
|
+
switch_info.state_service_name_list = NULL;
|
568
570
|
|
569
571
|
stop_trema();
|
570
572
|
}
|
@@ -578,7 +580,7 @@ unregistration_timeout( void *user_data ) {
|
|
578
580
|
|
579
581
|
warn( "Unregistration timeout ( datapath id %#" PRIx64 " ).", sw_info->datapath_id );
|
580
582
|
|
581
|
-
stop_switch(
|
583
|
+
stop_switch();
|
582
584
|
}
|
583
585
|
|
584
586
|
|
@@ -649,7 +651,7 @@ switch_event_disconnected( struct switch_info *sw_info ) {
|
|
649
651
|
}
|
650
652
|
else {
|
651
653
|
error( "Failed to send switch list request to switch manager." );
|
652
|
-
stop_switch(
|
654
|
+
stop_switch();
|
653
655
|
}
|
654
656
|
|
655
657
|
return 0;
|
@@ -661,7 +663,7 @@ unregistration_retry( void *user_data ) {
|
|
661
663
|
struct switch_info *sw_info = user_data;
|
662
664
|
|
663
665
|
if ( sw_info->retry_count == 0 ) {
|
664
|
-
stop_switch(
|
666
|
+
stop_switch();
|
665
667
|
return;
|
666
668
|
}
|
667
669
|
sw_info->retry_count--;
|
@@ -673,7 +675,7 @@ unregistration_retry( void *user_data ) {
|
|
673
675
|
}
|
674
676
|
else {
|
675
677
|
error( "Failed to send switch list request to switch manager." );
|
676
|
-
stop_switch(
|
678
|
+
stop_switch();
|
677
679
|
}
|
678
680
|
}
|
679
681
|
|
@@ -700,7 +702,8 @@ confirm_self_dpid_is_unregistered( const list_element *switches, void *user_data
|
|
700
702
|
}
|
701
703
|
else {
|
702
704
|
// The switch has been deleted from the switch list
|
703
|
-
|
705
|
+
finalize_openflow_application_interface();
|
706
|
+
push_external_callback( stop_switch );
|
704
707
|
}
|
705
708
|
}
|
706
709
|
|
@@ -881,9 +884,7 @@ static void
|
|
881
884
|
handle_sigterm( int signum ) {
|
882
885
|
UNUSED( signum );
|
883
886
|
|
884
|
-
|
885
|
-
stop_trema();
|
886
|
-
}
|
887
|
+
push_external_callback( stop_switch_daemon );
|
887
888
|
}
|
888
889
|
|
889
890
|
|
@@ -36,6 +36,9 @@
|
|
36
36
|
#include "event_forward_entry_manipulation.h"
|
37
37
|
|
38
38
|
|
39
|
+
#define DEFAULT_TCP_PORT 6653
|
40
|
+
|
41
|
+
|
39
42
|
#ifdef UNIT_TESTING
|
40
43
|
#define static
|
41
44
|
|
@@ -133,11 +136,11 @@ void mock_start_trema( void );
|
|
133
136
|
#define get_executable_name mock_get_executable_name
|
134
137
|
const char *mock_get_executable_name( void );
|
135
138
|
|
136
|
-
#ifdef
|
137
|
-
#undef
|
139
|
+
#ifdef push_external_callback
|
140
|
+
#undef push_external_callback
|
138
141
|
#endif
|
139
|
-
#define
|
140
|
-
void
|
142
|
+
#define push_external_callback mock_push_external_callback
|
143
|
+
void mock_push_external_callback( void ( *callback )( void ) );
|
141
144
|
|
142
145
|
#endif // UNIT_TESTING
|
143
146
|
|
@@ -168,7 +171,7 @@ usage() {
|
|
168
171
|
" -g, --syslog output log messages to syslog\n"
|
169
172
|
" -f, --logging_facility=FACILITY set syslog facility\n"
|
170
173
|
" -h, --help display this help and exit\n"
|
171
|
-
, get_executable_name(),
|
174
|
+
, get_executable_name(), DEFAULT_TCP_PORT
|
172
175
|
);
|
173
176
|
}
|
174
177
|
|
@@ -203,8 +206,8 @@ handle_sigchld( int signum ) {
|
|
203
206
|
UNUSED( signum );
|
204
207
|
|
205
208
|
// because wait_child() is not signal safe, we call it later.
|
206
|
-
if (
|
207
|
-
|
209
|
+
if ( push_external_callback != NULL ) {
|
210
|
+
push_external_callback( wait_child );
|
208
211
|
}
|
209
212
|
}
|
210
213
|
|
@@ -254,7 +257,7 @@ static void
|
|
254
257
|
init_listener_info( struct listener_info *listener_info ) {
|
255
258
|
memset( listener_info, 0, sizeof( struct listener_info ) );
|
256
259
|
listener_info->switch_daemon = xconcatenate_path( get_trema_home(), SWITCH_MANAGER_PATH );
|
257
|
-
listener_info->listen_port =
|
260
|
+
listener_info->listen_port = DEFAULT_TCP_PORT;
|
258
261
|
listener_info->listen_fd = -1;
|
259
262
|
create_list( &listener_info->vendor_service_name_list );
|
260
263
|
create_list( &listener_info->packetin_service_name_list );
|
@@ -555,7 +558,20 @@ start_switch_management( void ) {
|
|
555
558
|
|
556
559
|
static void
|
557
560
|
stop_switch_management( void ) {
|
558
|
-
|
561
|
+
if ( listener_info.listen_fd > -1 ) {
|
562
|
+
set_readable( listener_info.listen_fd, false );
|
563
|
+
delete_fd_handler( listener_info.listen_fd );
|
564
|
+
listener_info.listen_fd = -1;
|
565
|
+
}
|
566
|
+
stop_trema();
|
567
|
+
}
|
568
|
+
|
569
|
+
|
570
|
+
static void
|
571
|
+
handle_sigterm( int signum ) {
|
572
|
+
UNUSED( signum );
|
573
|
+
|
574
|
+
push_external_callback( stop_switch_management );
|
559
575
|
}
|
560
576
|
|
561
577
|
|
@@ -591,6 +607,12 @@ main( int argc, char *argv[] ) {
|
|
591
607
|
// free returned buffer of get_current_dir_name()
|
592
608
|
free( startup_dir );
|
593
609
|
|
610
|
+
struct sigaction signal_exit;
|
611
|
+
memset( &signal_exit, 0, sizeof( struct sigaction ) );
|
612
|
+
signal_exit.sa_handler = handle_sigterm;
|
613
|
+
sigaction( SIGINT, &signal_exit, NULL );
|
614
|
+
sigaction( SIGTERM, &signal_exit, NULL );
|
615
|
+
|
594
616
|
catch_sigchild();
|
595
617
|
|
596
618
|
// listener start (listen socket binding and listen)
|
@@ -606,7 +628,6 @@ main( int argc, char *argv[] ) {
|
|
606
628
|
start_trema();
|
607
629
|
|
608
630
|
finalize_listener_info( &listener_info );
|
609
|
-
stop_switch_management();
|
610
631
|
stop_service_management();
|
611
632
|
finalize_dpid_table();
|
612
633
|
|
@@ -27,6 +27,7 @@
|
|
27
27
|
#include <pthread.h>
|
28
28
|
#include <string.h>
|
29
29
|
#include <time.h>
|
30
|
+
#include "external_callback.h"
|
30
31
|
#include "pcap_private.h"
|
31
32
|
#include "queue.h"
|
32
33
|
#include "trema.h"
|
@@ -303,8 +304,8 @@ static void
|
|
303
304
|
start_packet_capture( void ) {
|
304
305
|
set_timer_event();
|
305
306
|
|
306
|
-
if (
|
307
|
-
|
307
|
+
if ( push_external_callback != NULL ) {
|
308
|
+
push_external_callback( start_capture );
|
308
309
|
}
|
309
310
|
}
|
310
311
|
|
data/src/tremashark/tremashark.c
CHANGED
@@ -350,8 +350,8 @@ write_circular_buffer( void ) {
|
|
350
350
|
|
351
351
|
static void
|
352
352
|
set_write_circular_buffer( void ) {
|
353
|
-
if (
|
354
|
-
|
353
|
+
if ( push_external_callback != NULL ) {
|
354
|
+
push_external_callback( write_circular_buffer );
|
355
355
|
}
|
356
356
|
}
|
357
357
|
|
data/trema.gemspec
CHANGED
@@ -28,7 +28,7 @@ Gem::Specification.new do | gem |
|
|
28
28
|
gem.add_dependency "bundler"
|
29
29
|
gem.add_dependency "gli", "~> 2.8.1"
|
30
30
|
gem.add_dependency "paper_house", "~> 0.5.0"
|
31
|
-
gem.add_dependency "pio", "~> 0.
|
31
|
+
gem.add_dependency "pio", "~> 0.3.0"
|
32
32
|
gem.add_dependency "rake", "~> 10.1.0"
|
33
33
|
gem.add_dependency "rdoc", "~> 4.0.1"
|
34
34
|
end
|
@@ -0,0 +1,282 @@
|
|
1
|
+
/*
|
2
|
+
* Unit tests for external_callback.
|
3
|
+
*
|
4
|
+
* Copyright (C) 2013 NEC Corporation
|
5
|
+
*
|
6
|
+
* This program is free software; you can redistribute it and/or modify
|
7
|
+
* it under the terms of the GNU General Public License, version 2, as
|
8
|
+
* published by the Free Software Foundation.
|
9
|
+
*
|
10
|
+
* This program is distributed in the hope that it will be useful,
|
11
|
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12
|
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
13
|
+
* GNU General Public License for more details.
|
14
|
+
*
|
15
|
+
* You should have received a copy of the GNU General Public License along
|
16
|
+
* with this program; if not, write to the Free Software Foundation, Inc.,
|
17
|
+
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
18
|
+
*/
|
19
|
+
|
20
|
+
|
21
|
+
#include <limits.h>
|
22
|
+
#include <stdio.h>
|
23
|
+
#include <string.h>
|
24
|
+
#include "checks.h"
|
25
|
+
#include "cmockery_trema.h"
|
26
|
+
#include "external_callback.h"
|
27
|
+
#include "utility.h"
|
28
|
+
|
29
|
+
typedef struct {
|
30
|
+
external_callback_t *buffer;
|
31
|
+
unsigned int size;
|
32
|
+
unsigned int write_position;
|
33
|
+
unsigned int read_position;
|
34
|
+
} ring_buffer;
|
35
|
+
|
36
|
+
#define MAX_EXTERNAL_CALLBACK 16
|
37
|
+
extern ring_buffer *external_callbacks;
|
38
|
+
|
39
|
+
|
40
|
+
/********************************************************************************
|
41
|
+
* Mock functions.
|
42
|
+
********************************************************************************/
|
43
|
+
|
44
|
+
static ring_buffer ring_buffer0;
|
45
|
+
static external_callback_t buffer0[ MAX_EXTERNAL_CALLBACK ];
|
46
|
+
|
47
|
+
void *
|
48
|
+
mock_xcalloc( size_t nmemb, size_t size ) {
|
49
|
+
check_expected( nmemb );
|
50
|
+
check_expected( size );
|
51
|
+
return ( void * ) ( intptr_t ) mock();
|
52
|
+
}
|
53
|
+
|
54
|
+
|
55
|
+
void
|
56
|
+
mock_xfree( void *ptr ) {
|
57
|
+
check_expected( ptr );
|
58
|
+
}
|
59
|
+
|
60
|
+
|
61
|
+
void
|
62
|
+
mock_debug( const char *format, ... ) {
|
63
|
+
UNUSED( format );
|
64
|
+
}
|
65
|
+
|
66
|
+
|
67
|
+
static void
|
68
|
+
reset() {
|
69
|
+
external_callbacks = NULL;
|
70
|
+
}
|
71
|
+
|
72
|
+
|
73
|
+
static void
|
74
|
+
setup() {
|
75
|
+
memset( &ring_buffer0, 0, sizeof( ring_buffer0 ) );
|
76
|
+
memset( buffer0, 0, sizeof( buffer0 ) );
|
77
|
+
external_callbacks = &ring_buffer0;
|
78
|
+
external_callbacks->buffer = buffer0;
|
79
|
+
external_callbacks->size = MAX_EXTERNAL_CALLBACK;
|
80
|
+
external_callbacks->write_position = 0;
|
81
|
+
external_callbacks->read_position = 0;
|
82
|
+
}
|
83
|
+
|
84
|
+
|
85
|
+
static void
|
86
|
+
teardown() {
|
87
|
+
external_callbacks = NULL;
|
88
|
+
}
|
89
|
+
|
90
|
+
|
91
|
+
/********************************************************************************
|
92
|
+
* Tests.
|
93
|
+
********************************************************************************/
|
94
|
+
|
95
|
+
static void
|
96
|
+
test_init_external_callback() {
|
97
|
+
expect_value( mock_xcalloc, nmemb, 1 );
|
98
|
+
expect_value( mock_xcalloc, size, sizeof( ring_buffer ) );
|
99
|
+
memset( &ring_buffer0, 0, sizeof( ring_buffer0 ) );
|
100
|
+
will_return( mock_xcalloc, &ring_buffer0 );
|
101
|
+
expect_value( mock_xcalloc, nmemb, MAX_EXTERNAL_CALLBACK );
|
102
|
+
expect_value( mock_xcalloc, size, sizeof( external_callback_t ) );
|
103
|
+
memset( buffer0, 0, sizeof( buffer0 ) );
|
104
|
+
will_return( mock_xcalloc, buffer0 );
|
105
|
+
|
106
|
+
init_external_callback();
|
107
|
+
|
108
|
+
assert_true( external_callbacks == &ring_buffer0 );
|
109
|
+
assert_true( external_callbacks->buffer == buffer0 );
|
110
|
+
assert_true( external_callbacks->size == MAX_EXTERNAL_CALLBACK );
|
111
|
+
assert_true( external_callbacks->write_position == 0 );
|
112
|
+
assert_true( external_callbacks->read_position == 0 );
|
113
|
+
}
|
114
|
+
|
115
|
+
|
116
|
+
static void
|
117
|
+
test_init_external_callback_fails_if_already_initialized() {
|
118
|
+
expect_assert_failure( init_external_callback() );
|
119
|
+
}
|
120
|
+
|
121
|
+
|
122
|
+
static void
|
123
|
+
test_finalize_external_callback() {
|
124
|
+
expect_value( mock_xfree, ptr, buffer0 );
|
125
|
+
expect_value( mock_xfree, ptr, &ring_buffer0 );
|
126
|
+
|
127
|
+
finalize_external_callback();
|
128
|
+
|
129
|
+
assert_true( external_callbacks == NULL );
|
130
|
+
}
|
131
|
+
|
132
|
+
|
133
|
+
static void
|
134
|
+
test_finalize_external_callback_fails_if_not_initialized() {
|
135
|
+
expect_assert_failure( finalize_external_callback() );
|
136
|
+
}
|
137
|
+
|
138
|
+
|
139
|
+
static void
|
140
|
+
test_finalize_external_callback_fails_if_already_finalized() {
|
141
|
+
expect_value( mock_xfree, ptr, buffer0 );
|
142
|
+
expect_value( mock_xfree, ptr, &ring_buffer0 );
|
143
|
+
finalize_external_callback();
|
144
|
+
|
145
|
+
expect_assert_failure( finalize_external_callback() );
|
146
|
+
}
|
147
|
+
|
148
|
+
|
149
|
+
static void
|
150
|
+
external_callback_helper() {
|
151
|
+
mock();
|
152
|
+
}
|
153
|
+
|
154
|
+
|
155
|
+
static void
|
156
|
+
test_push_external_callback() {
|
157
|
+
push_external_callback( external_callback_helper );
|
158
|
+
|
159
|
+
assert_true( external_callbacks->write_position == 1 );
|
160
|
+
assert_true( external_callbacks->read_position == 0 );
|
161
|
+
assert_true( external_callbacks->buffer[ 0 ] == external_callback_helper );
|
162
|
+
for ( int i = 1; i < MAX_EXTERNAL_CALLBACK; i++ ) {
|
163
|
+
assert_true( external_callbacks->buffer[ i ] == NULL );
|
164
|
+
}
|
165
|
+
}
|
166
|
+
|
167
|
+
|
168
|
+
static void
|
169
|
+
test_push_external_callback_fails_if_callback_is_NULL() {
|
170
|
+
assert_true( push_external_callback( NULL ) == false );
|
171
|
+
}
|
172
|
+
|
173
|
+
|
174
|
+
static void
|
175
|
+
test_push_external_callback_fails_if_not_initialized() {
|
176
|
+
assert_true( push_external_callback( external_callback_helper ) == false );
|
177
|
+
}
|
178
|
+
|
179
|
+
|
180
|
+
static void
|
181
|
+
test_push_external_callback_succeeds_with_multiple_callbacks() {
|
182
|
+
external_callbacks->write_position = 5;
|
183
|
+
external_callbacks->read_position = 5;
|
184
|
+
|
185
|
+
for ( int i = 0; i < MAX_EXTERNAL_CALLBACK; i++ ) {
|
186
|
+
push_external_callback( external_callback_helper );
|
187
|
+
}
|
188
|
+
|
189
|
+
assert_true( external_callbacks->write_position == 5 + MAX_EXTERNAL_CALLBACK );
|
190
|
+
assert_true( external_callbacks->read_position == 5 );
|
191
|
+
for ( int i = 0; i < MAX_EXTERNAL_CALLBACK; i++ ) {
|
192
|
+
assert_true( external_callbacks->buffer[ i ] == external_callback_helper );
|
193
|
+
}
|
194
|
+
}
|
195
|
+
|
196
|
+
|
197
|
+
static void
|
198
|
+
test_push_external_callback_fails_if_buffer_overflows() {
|
199
|
+
external_callbacks->write_position = 3;
|
200
|
+
external_callbacks->read_position = 3;
|
201
|
+
|
202
|
+
for ( int i = 0; i < MAX_EXTERNAL_CALLBACK; i++ ) {
|
203
|
+
push_external_callback( external_callback_helper );
|
204
|
+
}
|
205
|
+
expect_assert_failure( push_external_callback( external_callback_helper ) );
|
206
|
+
}
|
207
|
+
|
208
|
+
|
209
|
+
static void
|
210
|
+
test_run_external_callback() {
|
211
|
+
external_callbacks->write_position = UINT_MAX;
|
212
|
+
external_callbacks->read_position = UINT_MAX;
|
213
|
+
push_external_callback( external_callback_helper );
|
214
|
+
assert_true( external_callbacks->write_position == UINT_MAX + 1 );
|
215
|
+
assert_true( external_callbacks->read_position == UINT_MAX );
|
216
|
+
will_return( external_callback_helper, 0 );
|
217
|
+
|
218
|
+
run_external_callback();
|
219
|
+
|
220
|
+
assert_true( external_callbacks->write_position == UINT_MAX + 1 );
|
221
|
+
assert_true( external_callbacks->read_position == UINT_MAX + 1 );
|
222
|
+
for ( int i = 0; i < MAX_EXTERNAL_CALLBACK; i++ ) {
|
223
|
+
assert_true( external_callbacks->buffer[ i ] == NULL );
|
224
|
+
}
|
225
|
+
}
|
226
|
+
|
227
|
+
|
228
|
+
static void
|
229
|
+
test_run_external_callback_succeeds_with_multiple_callbacks() {
|
230
|
+
external_callbacks->write_position = UINT_MAX;
|
231
|
+
external_callbacks->read_position = UINT_MAX;
|
232
|
+
for ( int i = 0; i < MAX_EXTERNAL_CALLBACK; i++ ) {
|
233
|
+
push_external_callback( external_callback_helper );
|
234
|
+
}
|
235
|
+
assert_true( external_callbacks->write_position == UINT_MAX + MAX_EXTERNAL_CALLBACK );
|
236
|
+
assert_true( external_callbacks->read_position == UINT_MAX );
|
237
|
+
will_return_count( external_callback_helper, 0, MAX_EXTERNAL_CALLBACK );
|
238
|
+
|
239
|
+
run_external_callback();
|
240
|
+
|
241
|
+
assert_true( external_callbacks->write_position == UINT_MAX + MAX_EXTERNAL_CALLBACK );
|
242
|
+
assert_true( external_callbacks->read_position == UINT_MAX + MAX_EXTERNAL_CALLBACK );
|
243
|
+
for ( int i = 0; i < MAX_EXTERNAL_CALLBACK; i++ ) {
|
244
|
+
assert_true( external_callbacks->buffer[ i ] == NULL );
|
245
|
+
}
|
246
|
+
}
|
247
|
+
|
248
|
+
/********************************************************************************
|
249
|
+
* Run tests.
|
250
|
+
********************************************************************************/
|
251
|
+
|
252
|
+
int
|
253
|
+
main() {
|
254
|
+
const UnitTest tests[] = {
|
255
|
+
unit_test_setup_teardown( test_init_external_callback, reset, teardown ),
|
256
|
+
unit_test_setup_teardown( test_init_external_callback_fails_if_already_initialized, setup, teardown ),
|
257
|
+
|
258
|
+
unit_test_setup_teardown( test_finalize_external_callback, setup, teardown ),
|
259
|
+
unit_test_setup_teardown( test_finalize_external_callback_fails_if_not_initialized, reset, teardown ),
|
260
|
+
unit_test_setup_teardown( test_finalize_external_callback_fails_if_already_finalized, setup, teardown ),
|
261
|
+
|
262
|
+
unit_test_setup_teardown( test_push_external_callback, setup, teardown ),
|
263
|
+
unit_test_setup_teardown( test_push_external_callback_fails_if_callback_is_NULL, setup, teardown ),
|
264
|
+
unit_test_setup_teardown( test_push_external_callback_fails_if_not_initialized, reset, teardown ),
|
265
|
+
|
266
|
+
unit_test_setup_teardown( test_push_external_callback_succeeds_with_multiple_callbacks, setup, teardown ),
|
267
|
+
unit_test_setup_teardown( test_push_external_callback_fails_if_buffer_overflows, setup, teardown ),
|
268
|
+
|
269
|
+
unit_test_setup_teardown( test_run_external_callback, setup, teardown ),
|
270
|
+
unit_test_setup_teardown( test_run_external_callback_succeeds_with_multiple_callbacks, setup, teardown ),
|
271
|
+
};
|
272
|
+
|
273
|
+
return run_tests( tests );
|
274
|
+
}
|
275
|
+
|
276
|
+
|
277
|
+
/*
|
278
|
+
* Local variables:
|
279
|
+
* c-basic-offset: 2
|
280
|
+
* indent-tabs-mode: nil
|
281
|
+
* End:
|
282
|
+
*/
|