trema 0.4.5 → 0.4.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (56) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +4 -4
  3. data/Guardfile +8 -0
  4. data/Rakefile +2 -1
  5. data/bin/trema +4 -0
  6. data/cruise.rb +1 -1
  7. data/features/core/switch_manager.feature +2 -2
  8. data/features/examples/message.vendor-action.feature +2 -2
  9. data/features/examples/message.vendor-stats-request.feature +20 -0
  10. data/features/trema_commands/kill.feature +4 -0
  11. data/features/trema_commands/killall.feature +1 -0
  12. data/features/trema_commands/run.feature +20 -1
  13. data/ruby/trema/command/run.rb +4 -0
  14. data/ruby/trema/default_openflow_channel_port.rb +26 -0
  15. data/ruby/trema/dsl/configuration.rb +2 -1
  16. data/ruby/trema/open-vswitch.rb +2 -4
  17. data/ruby/trema/stats-reply.c +10 -1
  18. data/ruby/trema/stats-request.c +34 -1
  19. data/ruby/trema/vendor-stats-reply.rb +6 -2
  20. data/ruby/trema/version.rb +1 -1
  21. data/spec/trema/dsl/runner_spec.rb +1 -1
  22. data/spec/trema/dsl/syntax_spec.rb +1 -1
  23. data/spec/trema/shell/vswitch_spec.rb +1 -1
  24. data/spec/trema/stats-reply_spec.rb +2 -1
  25. data/spec/trema/stats-request_spec.rb +11 -0
  26. data/src/examples/cbench_switch/cbench-switch.rb +1 -0
  27. data/src/examples/cbench_switch/cbench_switch.c +1 -1
  28. data/src/examples/openflow_message/vendor-action.rb +4 -4
  29. data/src/examples/openflow_message/vendor-stats-request.rb +66 -0
  30. data/src/examples/simple_router/arp-table.rb +6 -17
  31. data/src/examples/simple_router/interface.rb +20 -29
  32. data/src/examples/simple_router/routing-table.rb +15 -22
  33. data/src/examples/simple_router/simple-router.rb +75 -64
  34. data/src/lib/chibach.c +3 -2
  35. data/src/lib/event_handler.c +55 -23
  36. data/src/lib/event_handler.h +0 -5
  37. data/src/lib/external_callback.c +126 -0
  38. data/src/lib/external_callback.h +46 -0
  39. data/src/lib/messenger.c +58 -35
  40. data/src/lib/openflow_message.c +32 -11
  41. data/src/lib/trema.c +13 -7
  42. data/src/lib/trema.h +1 -0
  43. data/src/lib/utility.c +13 -2
  44. data/src/switch_manager/secure_channel_receiver.c +6 -1
  45. data/src/switch_manager/switch.c +27 -26
  46. data/src/switch_manager/switch_manager.c +31 -10
  47. data/src/tremashark/packet_capture.c +3 -2
  48. data/src/tremashark/tremashark.c +2 -2
  49. data/trema.gemspec +1 -1
  50. data/unittests/lib/external_callback_test.c +282 -0
  51. data/unittests/lib/messenger_test.c +22 -0
  52. data/unittests/lib/openflow_message_test.c +1 -1
  53. data/unittests/lib/trema_test.c +1 -1
  54. data/unittests/switch_manager/switch_manager_test.c +3 -3
  55. metadata +12 -6
  56. data/src/examples/simple_router/router-utils.rb +0 -211
@@ -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 ( ( port_no == 0 ) || ( ( port_no > OFPP_MAX ) && ( port_no < OFPP_IN_PORT ) ) ) {
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 = validate_phy_port_no( ntohs( packet_in->in_port ) );
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 = validate_phy_port_no( ntohs( packet_out->in_port ) );
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
- if ( ntohs( flow_mod->out_port ) != OFPP_NONE ) {
2231
- ret = validate_phy_port_no( ntohs( flow_mod->out_port ) );
2232
- if ( ret < 0 ) {
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 = validate_phy_port_no( ntohs( flow_stats_request->out_port ) );
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 = validate_phy_port_no( ntohs( aggregate_stats_request->out_port ) );
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 = validate_phy_port_no( output.port );
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 set_external_callback
242
- #undef set_external_callback
241
+ #ifdef push_external_callback
242
+ #undef push_external_callback
243
243
  #endif
244
- #define set_external_callback mock_set_external_callback
245
- bool mock_set_external_callback( void ( *callback )( void ) );
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 * ) stop_trema;
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
- set_external_callback( do_restart_log );
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
- set_external_callback( dump_stats );
550
+ push_external_callback( dump_stats );
545
551
  }
546
552
 
547
553
 
data/src/lib/trema.h CHANGED
@@ -30,6 +30,7 @@
30
30
  #include "etherip.h"
31
31
  #include "event_forward_interface.h"
32
32
  #include "event_handler.h"
33
+ #include "external_callback.h"
33
34
  #include "hash_table.h"
34
35
  #include "linked_list.h"
35
36
  #include "log.h"
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
- for ( int i = 0; i < size; i++ ) {
72
- hash_value ^= ( unsigned char ) c[ i ];
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
- error( "Receive error:%s(%d)", strerror( errno ), errno );
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 ) {
@@ -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( struct switch_info *sw_info ) {
544
- if ( sw_info->secure_channel_fd >= 0 ) {
545
- close( sw_info->secure_channel_fd );
546
- sw_info->secure_channel_fd = -1;
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 ( sw_info->state == SWITCH_STATE_CONNECTION_FAILED ) {
551
+ if ( switch_info.state == SWITCH_STATE_CONNECTION_FAILED ) {
550
552
  state = MESSENGER_OPENFLOW_FAILD_TO_CONNECT;
551
553
  }
552
- service_send_state( sw_info, &sw_info->datapath_id, 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( sw_info->vendor_service_name_list, xfree_data, NULL );
557
- delete_list( sw_info->vendor_service_name_list );
558
- sw_info->vendor_service_name_list = NULL;
559
- iterate_list( sw_info->packetin_service_name_list, xfree_data, NULL );
560
- delete_list( sw_info->packetin_service_name_list );
561
- sw_info->packetin_service_name_list = NULL;
562
- iterate_list( sw_info->portstatus_service_name_list, xfree_data, NULL );
563
- delete_list( sw_info->portstatus_service_name_list );
564
- sw_info->portstatus_service_name_list = NULL;
565
- iterate_list( sw_info->state_service_name_list, xfree_data, NULL );
566
- delete_list( sw_info->state_service_name_list );
567
- sw_info->state_service_name_list = NULL;
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( sw_info );
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( sw_info );
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( sw_info );
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( sw_info );
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
- stop_switch( sw_info );
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
- if ( !set_external_callback( stop_switch_daemon ) ) {
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 set_external_callback
137
- #undef set_external_callback
139
+ #ifdef push_external_callback
140
+ #undef push_external_callback
138
141
  #endif
139
- #define set_external_callback mock_set_external_callback
140
- void mock_set_external_callback( void ( *callback )( 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(), OFP_TCP_PORT
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 ( set_external_callback != NULL ) {
207
- set_external_callback( wait_child );
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 = OFP_TCP_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
- // do something here.
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 ( set_external_callback != NULL ) {
307
- set_external_callback( start_capture );
307
+ if ( push_external_callback != NULL ) {
308
+ push_external_callback( start_capture );
308
309
  }
309
310
  }
310
311
 
@@ -350,8 +350,8 @@ write_circular_buffer( void ) {
350
350
 
351
351
  static void
352
352
  set_write_circular_buffer( void ) {
353
- if ( set_external_callback != NULL ) {
354
- set_external_callback( write_circular_buffer );
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.2.6"
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
+ */