trema 0.4.5 → 0.4.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|
+
*/
|