From b8255f3f8122c6af15490023f868464b32ee2628 Mon Sep 17 00:00:00 2001 From: Eishun Kondoh Date: Thu, 11 Apr 2019 23:52:24 +0900 Subject: [PATCH] quality: Add test cases for openflow actions --- lib/openflow/actions/nx_flow_spec_match.ex | 24 +++++++- lib/openflow/actions/nx_flow_spec_output.ex | 33 ++++++++--- test/ofp_action_test.exs | 66 +++++++++++++++++++++ 3 files changed, 113 insertions(+), 10 deletions(-) diff --git a/lib/openflow/actions/nx_flow_spec_match.ex b/lib/openflow/actions/nx_flow_spec_match.ex index feae23d..22312a9 100644 --- a/lib/openflow/actions/nx_flow_spec_match.ex +++ b/lib/openflow/actions/nx_flow_spec_match.ex @@ -13,12 +13,28 @@ defmodule Openflow.Action.NxFlowSpecMatch do alias __MODULE__ - def new(options) do - dst = options[:dst] + @type t :: %NxFlowSpecMatch{ + src: atom(), + dst: atom(), + n_bits: non_neg_integer(), + src_offset: non_neg_integer(), + dst_offset: non_neg_integer() + } + + @spec new( + src: atom(), + dst: atom(), + n_bits: non_neg_integer(), + src_offset: non_neg_integer(), + dst_offset: non_neg_integer() + ) :: t() + def new(options \\ []) do + dst = options[:dst] || raise ":dst must be specified" + src = options[:src] || raise ":src must be specified" n_bits = options[:n_bits] || Openflow.Match.Field.n_bits_of(dst) %NxFlowSpecMatch{ - src: options[:src], + src: src, dst: dst, n_bits: n_bits, src_offset: options[:src_offset] || 0, @@ -26,6 +42,7 @@ defmodule Openflow.Action.NxFlowSpecMatch do } end + @spec to_binary(t()) :: binary() def to_binary(%NxFlowSpecMatch{} = fsm) do %NxFlowSpecMatch{ dst: dst_field, @@ -48,6 +65,7 @@ defmodule Openflow.Action.NxFlowSpecMatch do end end + @spec read(binary()) :: {t(), binary()} def read( <<_::2, @learn_src_field::1, @learn_dst::2, n_bits::11, src_bin::4-bytes, src_ofs::16, dst_bin::4-bytes, dst_ofs::16, rest::bitstring>> diff --git a/lib/openflow/actions/nx_flow_spec_output.ex b/lib/openflow/actions/nx_flow_spec_output.ex index 7f0500b..87980f7 100644 --- a/lib/openflow/actions/nx_flow_spec_output.ex +++ b/lib/openflow/actions/nx_flow_spec_output.ex @@ -10,23 +10,42 @@ defmodule Openflow.Action.NxFlowSpecOutput do alias __MODULE__ - def new(options) do - src = options[:src] + @type t :: %NxFlowSpecOutput{ + n_bits: non_neg_integer(), + src: atom(), + src_offset: non_neg_integer() + } + + @spec new(src: atom(), n_bits: non_neg_integer(), src_offset: non_neg_integer()) :: t() + def new(options \\ []) do + src = options[:src] || raise ":src must be specified" n_bits = options[:n_bits] || Openflow.Match.Field.n_bits_of(src) %NxFlowSpecOutput{n_bits: n_bits, src: src, src_offset: options[:src_offset] || 0} end - def to_binary(%NxFlowSpecOutput{n_bits: n_bits, src: src, src_offset: src_ofs}) do - src_bin = Openflow.Match.codec_header(src) - <<0::2, @learn_src_field::1, @learn_dst::2, n_bits::11, src_bin::4-bytes, src_ofs::16>> + @spec to_binary(t()) :: binary() + def to_binary(%NxFlowSpecOutput{} = flow_spec) do + << + 0::2, + @learn_src_field::1, + @learn_dst::2, + flow_spec.n_bits::11, + Openflow.Match.codec_header(flow_spec.src)::4-bytes, + flow_spec.src_offset::16 + >> end + @spec read(binary()) :: {t(), binary()} def read( <<0::2, @learn_src_field::1, @learn_dst::2, n_bits::11, src_bin::4-bytes, src_ofs::16, rest::bitstring>> ) do - src = Openflow.Match.codec_header(src_bin) - flow_spec = %NxFlowSpecOutput{n_bits: n_bits, src: src, src_offset: src_ofs} + flow_spec = %NxFlowSpecOutput{ + n_bits: n_bits, + src: Openflow.Match.codec_header(src_bin), + src_offset: src_ofs + } + {flow_spec, rest} end end diff --git a/test/ofp_action_test.exs b/test/ofp_action_test.exs index 0d6bf8a..22579b9 100644 --- a/test/ofp_action_test.exs +++ b/test/ofp_action_test.exs @@ -733,6 +733,72 @@ defmodule OfpActionTest do end end + describe "Openflow.Action.NxFlowSpecOutput" do + test "with src = :in_port" do + flow_spec = Openflow.Action.NxFlowSpecOutput.new(src: :in_port) + + flow_spec + |> Openflow.Action.NxFlowSpec.to_binary() + |> Openflow.Action.NxFlowSpec.read() + |> Enum.at(0) + |> Kernel.==(flow_spec) + |> assert() + end + + test "with no options" do + assert_raise RuntimeError, ":src must be specified", fn -> + Openflow.Action.NxFlowSpecOutput.new() + end + end + end + + describe "Openflow.Action.NxFlowSpecMatch" do + test "with src = 0xdeadbeef and dst: :reg0" do + flow_spec = Openflow.Action.NxFlowSpecMatch.new(src: 0xDEADBEEF, dst: :reg0) + + flow_spec + |> Openflow.Action.NxFlowSpec.to_binary() + |> Openflow.Action.NxFlowSpec.read() + |> Enum.at(0) + |> Kernel.==(flow_spec) + |> assert() + end + + test "with src = :in_port and dst: :reg0" do + flow_spec = + Openflow.Action.NxFlowSpecMatch.new( + src: :in_port, + dst: :reg0, + n_bits: 16 + ) + + flow_spec + |> Openflow.Action.NxFlowSpec.to_binary() + |> Openflow.Action.NxFlowSpec.read() + |> Enum.at(0) + |> Kernel.==(flow_spec) + |> assert() + end + + test "with no option" do + assert_raise RuntimeError, ":dst must be specified", fn -> + Openflow.Action.NxFlowSpecMatch.new() + end + end + + test "with no dst option" do + assert_raise RuntimeError, ":dst must be specified", fn -> + Openflow.Action.NxFlowSpecMatch.new(src: :in_port) + end + end + + test "with no src option" do + assert_raise RuntimeError, ":src must be specified", fn -> + Openflow.Action.NxFlowSpecMatch.new(dst: :reg0) + end + end + end + describe "Openflow.Action.NxMultipath" do test "with multipath" do test_file = "test/packet_data/nx_multipath.raw"