Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Porting rspec into trema-edge #11

Open
nickkaranatsios opened this issue Jan 18, 2013 · 2 comments
Open

Porting rspec into trema-edge #11

nickkaranatsios opened this issue Jan 18, 2013 · 2 comments
Assignees

Comments

@nickkaranatsios
Copy link
Member

This issue also depends on the creation of trema shared library before it can be started.

@ghost ghost assigned nickkaranatsios Jan 18, 2013
@yasuhito
Copy link
Member

👍

@nickkaranatsios
Copy link
Member Author

@yasuhito I started porting the rspec into trema-edge but I found that the network{} block is a bit restrictive ( to be able to receive multiple events like switch_ready and/or packet_in or others ) so I am thinking about the following modifications but not really completely different from the original source:
Create a MockController class that accepts a network configuration block so when we set up all the conditions we can start the controller. Finally when we complete the test we stop the controller. An example is always better.

class MockController < Controller
  def initialize network_blk
    @network_blk = network_blk
    @context = Trema::DSL::Parser.new.eval( &network_blk )
  end


  def start_receiving
    if @network_blk.respond_to? :call
      trema_run
    else
      raise ArgumentError, "Network configuration should be a proc block"
    end
  end


  def stop_receiving
    trema_kill
  end


  def time_sleep interval
    sleep interval
    yield
  end


  # nearly the same as before.
  def trema_run
    controller = self
    if not controller.is_a?( Trema::Controller )
      raise "#{ controller_class } is not a subclass of Trema::Controller"
    end
    Trema::DSL::Context.new( @context ).dump

    app_name = controller.name
    rule = { :port_status => app_name, :packet_in => app_name, :state_notify => app_name }
    sm = SwitchManager.new( rule, @context.port )
    sm.no_flow_cleanup = true
    sm.run!

    @context.links.each do | name, each |
      each.add!
    end
    @context.hosts.each do | name, each |
      each.run!
    end
    @context.trema_switches.each do | name, each |
      each.run!
    end
    @context.links.each do | name, each |
      each.up!
    end
    @context.hosts.each do | name, each |
      each.add_arp_entry @context.hosts.values - [ each ]
    end

    @th_controller = Thread.start do
      controller.run!
    end
    sleep 2  # FIXME: wait until controller.up?
  end


  def trema_kill
    cleanup_current_session
    @th_controller.join if @th_controller
    sleep 2  # FIXME: wait until switch_manager.down?
  end
end

An example to show its use.

describe Trema::ArpOp, ".new( VALID OPTIONS )" do
  context "when setting a flow with a match field arp_op set to 1 and sending a ping packet" do
    it "should have its arp_op set to 1 when #packet-in" do
      network_blk = Proc.new {
        trema_switch( "lsw" ) { datapath_id 0xabc }
        vhost( "host1" ) {
          ip "192.168.0.1"
          netmask "255.255.255.0"
          mac "00:00:00:00:00:01"
        }
        vhost( "host2" ) {
          ip "192.168.0.2"
          netmask "255.255.255.0"
          mac "00:00:00:00:00:02"
        }
        link "host1", "lsw:1"
        link "host2", "lsw:2"
      }
      mc = MockController.new( network_blk )
      mc.should_receive( :switch_ready ) do | datapath_id |
        action = SendOutPort.new( port_number: OFPP_CONTROLLER )
        apply_ins = ApplyAction.new( actions: [ action ] )
        match_fields = Match.new( in_port: 1, eth_type: 2054, arp_op: 1 )
        mc.send_flow_mod_add( datapath_id,
                              cookie: 1111,
                              match: match_fields,
                              instructions: [ apply_ins ] )
      end
      mc.should_receive( :packet_in ).at_least( :once ) do | datapath_id, message |
        action = Trema::ArpOp.new( arp_op: 1 )
        expect( action.arp_op ).to  eq( message.packet_info.arp_op )
      end
      mc.start_receiving
      system( "ping -I trema1-0 -c 1 192.168.0.1" )
      mc.time_sleep( 2 ) {
        mc.stop_receiving
      }
    end
  end
end

The above describes one way to verify ArpOp flexible action. If you have any comments please inform me. I am planning to use the above spec_helper.rb to start creating rspecs for some more complicated cases and see if it meets all the needs or not.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants