[SEBA-918][VOL-2984] Allowing DHCP without completing eapol

For DT and TT workflow is required that DHCP is triggered without doing
anything for EAPOL. If you start BBSim with only the "-dhcp" option that
is now possible.

Change-Id: Iacfb75e70c47a2f7cfa64af58d6d848881f54974
diff --git a/internal/bbsim/devices/onu_state_machine_test.go b/internal/bbsim/devices/onu_state_machine_test.go
index 0bf4bed..81bf330 100644
--- a/internal/bbsim/devices/onu_state_machine_test.go
+++ b/internal/bbsim/devices/onu_state_machine_test.go
@@ -39,8 +39,8 @@
 	onu.PortNo = 16
 	onu.DhcpFlowReceived = true
 	onu.Flows = []FlowKey{
-		FlowKey{ID:1, Direction:"upstream"},
-		FlowKey{ID:2, Direction:"downstream"},
+		FlowKey{ID: 1, Direction: "upstream"},
+		FlowKey{ID: 2, Direction: "downstream"},
 	}
 
 	onu.InternalState.Event("disable")
@@ -51,38 +51,51 @@
 	assert.Equal(t, len(onu.Flows), 0)
 }
 
-func Test_Onu_StateMachine_eapol_start_eap_flow(t *testing.T) {
+// check that I can go to auth_started only if
+// - the GemPort is set
+// - the eapolFlow is received
+func Test_Onu_StateMachine_eapol_no_flow(t *testing.T) {
 	onu := createTestOnu()
 
 	onu.InternalState.SetState("enabled")
-
-	// TODO we need to add a check so that you can't go from eapol_flow_received
-	// to auth_started without passing through gem_port_added
-	// (see start_dhcp for an example)
-
 	assert.Equal(t, onu.InternalState.Current(), "enabled")
-	onu.InternalState.Event("receive_eapol_flow")
-	assert.Equal(t, onu.InternalState.Current(), "eapol_flow_received")
-	onu.InternalState.Event("add_gem_port")
-	assert.Equal(t, onu.InternalState.Current(), "gem_port_added")
-	onu.InternalState.Event("start_auth")
-	assert.Equal(t, onu.InternalState.Current(), "auth_started")
+
+	// fail as no EapolFlow has been received
+	err := onu.InternalState.Event("start_auth")
+	if err == nil {
+		t.Fatal("can't start EAPOL without EapolFlow")
+	}
+	assert.Equal(t, onu.InternalState.Current(), "enabled")
+	assert.Equal(t, err.Error(), "transition canceled with error: cannot-go-to-auth-started-as-eapol-flow-is-missing")
 }
 
-func Test_Onu_StateMachine_eapol_start_gem_port(t *testing.T) {
+func Test_Onu_StateMachine_eapol_no_gem(t *testing.T) {
 	onu := createTestOnu()
 
 	onu.InternalState.SetState("enabled")
-
-	// TODO we need to add a check so that you can't go from gem_port_added
-	// to auth_started without passing through eapol_flow_received
-	// (see start_dhcp for an example)
-
 	assert.Equal(t, onu.InternalState.Current(), "enabled")
-	onu.InternalState.Event("add_gem_port")
-	assert.Equal(t, onu.InternalState.Current(), "gem_port_added")
-	onu.InternalState.Event("receive_eapol_flow")
-	assert.Equal(t, onu.InternalState.Current(), "eapol_flow_received")
+	// fail has no GemPort has been set
+	onu.EapolFlowReceived = true
+
+	err := onu.InternalState.Event("start_auth")
+	if err == nil {
+		t.Fatal("can't start EAPOL without GemPort")
+	}
+	assert.Equal(t, onu.InternalState.Current(), "enabled")
+	assert.Equal(t, err.Error(), "transition canceled with error: cannot-go-to-auth-started-as-gemport-is-missing")
+
+}
+
+func Test_Onu_StateMachine_eapol_start(t *testing.T) {
+
+	onu := createTestOnu()
+
+	onu.InternalState.SetState("enabled")
+	assert.Equal(t, onu.InternalState.Current(), "enabled")
+
+	// succeed
+	onu.EapolFlowReceived = true
+	onu.GemPortAdded = true
 	onu.InternalState.Event("start_auth")
 	assert.Equal(t, onu.InternalState.Current(), "auth_started")
 }
@@ -90,6 +103,9 @@
 func Test_Onu_StateMachine_eapol_states(t *testing.T) {
 	onu := createTestOnu()
 
+	onu.GemPortAdded = true
+	onu.EapolFlowReceived = true
+
 	onu.InternalState.SetState("auth_started")
 
 	assert.Equal(t, onu.InternalState.Current(), "auth_started")
@@ -112,34 +128,77 @@
 	}
 }
 
+// if auth is set to true we can't go from enabled to dhcp_started
+func Test_Onu_StateMachine_dhcp_no_auth(t *testing.T) {
+	onu := createTestOnu()
+
+	onu.InternalState.SetState("enabled")
+	assert.Equal(t, onu.InternalState.Current(), "enabled")
+
+	onu.Auth = true
+
+	err := onu.InternalState.Event("start_dhcp")
+	if err == nil {
+		t.Fail()
+	}
+	assert.Equal(t, onu.InternalState.Current(), "enabled")
+	assert.Equal(t, err.Error(), "transition canceled with error: cannot-go-to-dhcp-started-as-authentication-is-required")
+}
+
+// if the DHCP flow has not been received we can't start authentication
+func Test_Onu_StateMachine_dhcp_no_flow(t *testing.T) {
+	onu := createTestOnu()
+
+	onu.InternalState.SetState("eap_response_success_received")
+	assert.Equal(t, onu.InternalState.Current(), "eap_response_success_received")
+
+	onu.DhcpFlowReceived = false
+
+	err := onu.InternalState.Event("start_dhcp")
+	if err == nil {
+		t.Fail()
+	}
+	assert.Equal(t, onu.InternalState.Current(), "eap_response_success_received")
+	assert.Equal(t, err.Error(), "transition canceled with error: cannot-go-to-dhcp-started-as-dhcp-flow-is-missing")
+}
+
+// if the ONU does not have a GemPort we can't start DHCP
+func Test_Onu_StateMachine_dhcp_no_gem(t *testing.T) {
+	onu := createTestOnu()
+
+	onu.InternalState.SetState("eap_response_success_received")
+	assert.Equal(t, onu.InternalState.Current(), "eap_response_success_received")
+
+	onu.DhcpFlowReceived = true
+	onu.GemPortAdded = false
+
+	err := onu.InternalState.Event("start_dhcp")
+	if err == nil {
+		t.Fail()
+	}
+	assert.Equal(t, onu.InternalState.Current(), "eap_response_success_received")
+	assert.Equal(t, err.Error(), "transition canceled with error: cannot-go-to-dhcp-started-as-gemport-is-missing")
+}
+
 func Test_Onu_StateMachine_dhcp_start(t *testing.T) {
 	onu := createTestOnu()
 	onu.DhcpFlowReceived = true
+	onu.GemPortAdded = true
+	onu.Auth = true
 
 	onu.InternalState.SetState("eap_response_success_received")
 	assert.Equal(t, onu.InternalState.Current(), "eap_response_success_received")
 
+	// default transition
 	onu.InternalState.Event("start_dhcp")
-
 	assert.Equal(t, onu.InternalState.Current(), "dhcp_started")
 }
 
-func Test_Onu_StateMachine_dhcp_start_error(t *testing.T) {
-	onu := createTestOnu()
-
-	onu.InternalState.SetState("eap_response_success_received")
-	assert.Equal(t, onu.InternalState.Current(), "eap_response_success_received")
-
-	err := onu.InternalState.Event("start_dhcp")
-
-	assert.Equal(t, onu.InternalState.Current(), "eap_response_success_received")
-	assert.Equal(t, err.Error(), "transition canceled with error: cannot-go-to-dhcp-started-as-dhcp-flow-is-missing")
-}
-
 func Test_Onu_StateMachine_dhcp_states(t *testing.T) {
 	onu := createTestOnu()
 
-	onu.DhcpFlowReceived = false
+	onu.DhcpFlowReceived = true
+	onu.GemPortAdded = true
 
 	onu.InternalState.SetState("dhcp_started")
 
@@ -152,7 +211,6 @@
 	assert.Equal(t, onu.InternalState.Current(), "dhcp_ack_received")
 
 	// test that we can retrigger DHCP
-	onu.DhcpFlowReceived = true
 	states := []string{"eap_response_success_received", "dhcp_discovery_sent", "dhcp_request_sent", "dhcp_ack_received", "dhcp_failed"}
 	for _, state := range states {
 		onu.InternalState.SetState(state)