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.
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
+ */