trema/trema-edge

View on GitHub
unittests/switch/switch/group-helper-test.c

Summary

Maintainability
Test Coverage
/*
 * Copyright (C) 2008-2013 NEC Corporation
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License, version 2, as
 * published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */


#include <stdio.h>
#include <string.h>
#include "trema.h"
#include "ofdp.h"
#include "group-helper.h"
#include "mocks.h"
#include "cmockery_trema.h"


#define DATAPATH_ID 0xabc
#define MY_TRANSACTION_ID 0x11223344
#define GROUP_ID 1
#define INVALID_GROUP_ID 3333
#define WATCH_GROUP_1 0xaa
#define WATCH_GROUP_2 0xbb
#define DEV_PORT_1 "trema1-0"
#define DEV_PORT_2 "trema2-0"
#define WATCH_PORT_1 1
#define WATCH_PORT_2 2
#define WEIGHT_1 123
#define WEIGHT_2 456


static void
test_create_group_mod( void **state ) {
  list_element *buckets_head;

  create_list( &buckets_head );
  size_t total_len = sizeof( struct ofp_bucket ) + sizeof( struct ofp_action_output ) ;
  struct ofp_bucket *bucket = ( struct ofp_bucket * ) ( xmalloc( total_len ) );
  bucket->len = ( uint16_t ) total_len;
  bucket->watch_group = WATCH_GROUP_1;
  bucket->watch_port = WATCH_PORT_1;
  bucket->weight = WEIGHT_1;
  struct ofp_action_output *ac_output = ( struct ofp_action_output * ) ( bucket->actions );
  ac_output->type = OFPAT_OUTPUT;
  ac_output->len = ( uint16_t ) sizeof( struct ofp_action_output );
  ac_output->port = 1;
  ac_output->max_len = 512;
  append_to_tail( &buckets_head, bucket );
  
  bucket = ( struct ofp_bucket * ) xmalloc( total_len );
  bucket->len = ( uint16_t ) total_len;
  bucket->watch_group = WATCH_GROUP_2;
  bucket->watch_port = WATCH_PORT_2;
  bucket->weight = WEIGHT_2;
  ac_output = ( struct ofp_action_output * ) ( char * ) ( bucket->actions );
  ac_output->type = OFPAT_OUTPUT;
  ac_output->len = ( uint16_t ) sizeof( struct ofp_action_output );
  ac_output->port = 2;
  ac_output->max_len = 1024;
  append_to_tail( &buckets_head, bucket );
  system( "sudo ip link add name trema1-0 type veth peer name trema1-1" );
  system( "sudo ip link add name trema2-0 type veth peer name trema2-1" );
  add_thread();
  init_event_handler_safe();
  init_timer_safe();
  init_table_manager( UINT8_MAX );
  init_switch_port();
  add_switch_port( DEV_PORT_1, WATCH_PORT_1, UINT8_MAX, UINT8_MAX );
  add_switch_port( DEV_PORT_2, WATCH_PORT_2, UINT8_MAX, UINT8_MAX );
  *state = ( void * ) buckets_head;
}


static void
test_destroy_group_mod( void **state ) {
  UNUSED( state );
  system( "sudo ip link delete trema1-0 2>/dev/null" );
  system( "sudo ip link delete trema2-0 2>/dev/null" );
  finalize_table_manager();
  finalize_switch_port();
  finalize_timer_safe();
  finalize_event_handler_safe();
}


static void
test_group_mod_add( void **state ) {
  list_element *buckets = *state;
  
  handle_group_add( MY_TRANSACTION_ID, OFPGT_SELECT, GROUP_ID, buckets );
  group_entry *group_entry = lookup_group_entry( GROUP_ID );
  assert_int_equal( group_entry->group_id, GROUP_ID );
  assert_int_equal( group_entry->type, OFPGT_SELECT );

  bucket_list *bkt_element = get_first_element( group_entry->buckets );
  if ( bkt_element->data == NULL ) {
    bkt_element = bkt_element->next;
  }
  bucket *bucket1 = bkt_element->data;
  struct ofp_bucket *ofp_bucket1 = buckets->data;

  assert_int_equal( bucket1->watch_group, ofp_bucket1->watch_group );
  assert_int_equal( bucket1->weight, ofp_bucket1->weight );
  assert_int_equal( bucket1->watch_port, ofp_bucket1->watch_port );

  action_list *ac_element = get_first_element( bucket1->actions );
  if ( ac_element->data == NULL ) {
    ac_element = ac_element->next;
  }
  action *ac1 = ac_element->data;
  struct ofp_action_output *ofp_ac_out1 = ( struct ofp_action_output * ) ofp_bucket1->actions;
  assert_int_equal( ac1->type, ofp_ac_out1->type );
  assert_int_equal( ac1->port, ofp_ac_out1->port );
  assert_int_equal( ac1->max_len, ofp_ac_out1->max_len );

  bucket *bucket2 = bkt_element->next->data;
  struct ofp_bucket *ofp_bucket2 = buckets->next->data;

  assert_int_equal( bucket2->watch_group, ofp_bucket2->watch_group );
  assert_int_equal( bucket2->weight, ofp_bucket2->weight );
  assert_int_equal( bucket2->watch_port, ofp_bucket2->watch_port );

  ac_element = get_first_element( bucket2->actions );
  if ( ac_element->data == NULL ) {
    ac_element = ac_element->next;
  }
  action *ac2 = ac_element->data;
  struct ofp_action_output *ofp_ac_out2 = ( struct ofp_action_output * ) ofp_bucket2->actions;
  assert_int_equal( ac2->type, ofp_ac_out2->type );
  assert_int_equal( ac2->port, ofp_ac_out2->port );
  assert_int_equal( ac2->max_len, ofp_ac_out2->max_len );
}


static void
test_group_mod_mod( void **state ) {
  list_element *buckets = *state;
  
  handle_group_add( MY_TRANSACTION_ID, OFPGT_SELECT, GROUP_ID, buckets );

 list_element *buckets_head;

  create_list( &buckets_head );
  size_t total_len = sizeof( struct ofp_bucket ) + sizeof( struct ofp_action_header ) ;
  struct ofp_bucket *ofp_bucket = ( struct ofp_bucket * ) ( xmalloc( total_len ) );

  ofp_bucket->len = ( uint16_t ) total_len;
  ofp_bucket->watch_group = WATCH_GROUP_1;
  ofp_bucket->watch_port = WATCH_PORT_1;
  ofp_bucket->weight = WEIGHT_1;
  struct ofp_action_header *ac_hdr = ( struct ofp_action_header * ) ( ofp_bucket->actions );
  ac_hdr->type = OFPAT_COPY_TTL_IN;
  ac_hdr->len = ( uint16_t ) sizeof( struct ofp_action_header );
  append_to_tail( &buckets_head, ofp_bucket );
 
  handle_group_mod_mod( MY_TRANSACTION_ID, OFPGT_ALL, GROUP_ID, buckets_head );
  group_entry *group_entry = lookup_group_entry( GROUP_ID );
  assert_int_equal( group_entry->group_id, GROUP_ID );

  bucket_list *bkt_element = get_first_element( group_entry->buckets );
  if ( bkt_element->data == NULL ) {
    bkt_element = bkt_element->next;
  }
  bucket *bucket = bkt_element->data; 
  assert_true( bucket );
  assert_int_equal( bucket->weight, WEIGHT_1 );
  assert_int_equal( bucket->watch_port, WATCH_PORT_1 );
  assert_int_equal( bucket->watch_group, WATCH_GROUP_1 );

  action_list *ac_element = get_first_element( bucket->actions );
  if ( ac_element->data == NULL ) {
    ac_element = ac_element->next;
  }
  action *action = ac_element->data;
  assert_true( action );
  assert_int_equal( action->type, OFPAT_COPY_TTL_IN );
}


static void
test_group_mod_delete( void **state ) {
  list_element *buckets = *state;

  handle_group_add( MY_TRANSACTION_ID, OFPGT_SELECT, GROUP_ID, buckets );
  handle_group_mod_delete( MY_TRANSACTION_ID, GROUP_ID );
  group_entry *group_entry = lookup_group_entry( GROUP_ID );
  assert_true( group_entry == NULL );
}
  

static void
test_group_mod_delete_invalid( void **state ) {
  list_element *buckets = *state;

  handle_group_add( MY_TRANSACTION_ID, OFPGT_SELECT, GROUP_ID, buckets );
  handle_group_mod_delete( MY_TRANSACTION_ID, INVALID_GROUP_ID );
  group_entry *group_entry = lookup_group_entry( GROUP_ID );
  assert_true( group_entry );
}

int
main() {
  const UnitTest tests[] = {
    unit_test_setup_teardown( test_group_mod_add, test_create_group_mod, test_destroy_group_mod ),
    unit_test_setup_teardown( test_group_mod_mod, test_create_group_mod, test_destroy_group_mod ),
    unit_test_setup_teardown( test_group_mod_delete, test_create_group_mod, test_destroy_group_mod ),
    unit_test_setup_teardown( test_group_mod_delete_invalid, test_create_group_mod, test_destroy_group_mod )
  };
  return run_tests( tests );
}


/*
 * Local variables:
 * c-basic-offset: 2
 * indent-tabs-mode: nil
 * End:
 */