BGP functional test suite improvements
[integration/test.git] / csit / suites / bgpcep / bgpuser / cases.robot
1 *** Settings ***
2 Documentation     Basic tests for odl-bgpcep-bgp-all feature.
3 ...
4 ...               Copyright (c) 2015 Cisco Systems, Inc. and others. All rights reserved.
5 ...
6 ...               This program and the accompanying materials are made available under the
7 ...               terms of the Eclipse Public License v1.0 which accompanies this distribution,
8 ...               and is available at http://www.eclipse.org/legal/epl-v10.html
9 ...
10 ...               Test suite performs basic BGP functional test cases:
11 ...               BGP peer initiated coonection
12 ...               - introduce and check 3 prefixes in one update message
13 ...               ODL controller initiated coonection:
14 ...               - introduce and check 3 prefixes in one update message
15 ...               - introduce 2 prefixes in first update message and then additional 2 prefixes
16 ...               in another update while the very first prefix is withdrawn
17 ...               - introduce 3 prefixes and try to withdraw the first one
18 ...               (to be ignored by controller) in a single update message
19 ...
20 ...               Brief description how to perform BGP functional test:
21 ...               https://wiki.opendaylight.org/view/BGP_LS_PCEP:Lithium_Feature_Tests#How_to_test_2
22 ...
23 ...               Reported bugs:
24 ...               https://bugs.opendaylight.org/show_bug.cgi?id=4409
25 ...               https://bugs.opendaylight.org/show_bug.cgi?id=4634
26 Suite Setup       Setup_Everything
27 Suite Teardown    Teardown_Everything
28 Test Setup        SetupUtils.Setup_Test_With_Logging_And_Fast_Failing
29 Test Teardown     FailFast.Start_Failing_Fast_If_This_Failed
30 Library           OperatingSystem
31 Library           SSHLibrary    timeout=10s
32 Library           RequestsLibrary
33 Library           ${CURDIR}/../../../libraries/HsfJson/hsf_json.py
34 Variables         ${CURDIR}/../../../variables/Variables.py
35 Variables         ${CURDIR}/../../../variables/bgpuser/variables.py    ${TOOLS_SYSTEM_IP}
36 Resource          ${CURDIR}/../../../libraries/BGPSpeaker.robot
37 Resource          ${CURDIR}/../../../libraries/ConfigViaRestconf.robot
38 Resource          ${CURDIR}/../../../libraries/FailFast.robot
39 Resource          ${CURDIR}/../../../libraries/KarafKeywords.robot
40 Resource          ${CURDIR}/../../../libraries/KillPythonTool.robot
41 Resource          ${CURDIR}/../../../libraries/SetupUtils.robot
42 Resource          ${CURDIR}/../../../libraries/SSHKeywords.robot
43 Resource          ${CURDIR}/../../../libraries/Utils.robot
44 Resource          ${CURDIR}/../../../libraries/WaitForFailure.robot
45
46 *** Variables ***
47 ${ACTUAL_RESPONSES_FOLDER}    ${TEMPDIR}/actual
48 ${EXPECTED_RESPONSES_FOLDER}    ${TEMPDIR}/expected
49 ${BGP_VARIABLES_FOLDER}    ${CURDIR}/../../../variables/bgpuser/
50 ${TOOLS_SYSTEM_PROMPT}    ${DEFAULT_LINUX_PROMPT}
51 ${HOLDTIME}       180
52 ${BGP_TOOL_LOG_LEVEL}    info
53 ${CONTROLLER_LOG_LEVEL}    INFO
54 ${CONTROLLER_BGP_LOG_LEVEL}    DEFAULT
55
56 *** Test Cases ***
57 Check_For_Empty_Topology_Before_Talking
58     [Documentation]    Sanity check example-ipv4-topology is up but empty.
59     [Tags]    critical
60     Wait_For_Topology_To_Change_To    ${empty_json}    010_Empty.json    timeout=120s
61     # TODO: Verify that 120 seconds is not too short if this suite is run immediatelly after ODL is started.
62
63 Reconfigure_ODL_To_Accept_Connection
64     [Documentation]    Configure BGP peer module with initiate-connection set to false.
65     ${template_as_string}=    BuiltIn.Set_Variable    {'NAME': 'example-bgp-peer', 'IP': '${TOOLS_SYSTEM_IP}', 'HOLDTIME': '${HOLDTIME}', 'PEER_PORT': '${BGP_TOOL_PORT}', 'INITIATE': 'false'}
66     ConfigViaRestconf.Put_Xml_Template_Folder_Config_Via_Restconf    ${BGP_VARIABLES_FOLDER}${/}bgp_peer    ${template_as_string}
67
68 Start_Talking_BGP_speaker
69     [Documentation]    Start Python speaker to connect to ODL, verify that the tool does not promptly exit.
70     # Myport value is needed for checking whether connection at precise port was established.
71     BGPSpeaker.Start_BGP_Speaker    --amount 3 --myip=${TOOLS_SYSTEM_IP} --myport=${BGP_TOOL_PORT} --peerip=${ODL_SYSTEM_IP} --peerport=${ODL_BGP_PORT} --${BGP_TOOL_LOG_LEVEL}
72     Read_And_Fail_If_Prompt_Is_Seen
73
74 Check_Talking_Connection_Is_Established
75     [Documentation]    See TCP (BGP) connection in established state.
76     # This case is separate from the previous one, to resemble structure of the second half of this suite more closely.
77     Check_Speaker_Is_Connected
78
79 Check_Talking_Topology_Is_Filled
80     [Documentation]    See new routes in example-ipv4-topology as a proof that synchronization was correct.
81     [Tags]    critical
82     Wait_For_Topology_To_Change_To    ${filled_json}    020_Filled.json
83
84 Kill_Talking_BGP_Speaker
85     [Documentation]    Abort the Python speaker. Also, attempt to stop failing fast.
86     [Tags]    critical
87     [Setup]    SetupUtils.Setup_Test_With_Logging_And_Without_Fast_Failing
88     BGPSpeaker.Kill_BGP_Speaker
89     FailFast.Do_Not_Fail_Fast_From_Now_On
90     # NOTE: It is still possible to remain failing fast, if both previous and this test have failed.
91     [Teardown]    FailFast.Do_Not_Start_Failing_If_This_Failed
92
93 Check_For_Empty_Topology_After_Talking
94     [Documentation]    See example-ipv4-topology empty again.
95     [Tags]    critical
96     Wait_For_Topology_To_Change_To    ${empty_json}    030_Empty.json
97
98 Start_Listening_BGP_Speaker
99     [Documentation]    Start Python speaker in listening mode, verify that the tool does not exit quickly.
100     BGPSpeaker.Start_BGP_Speaker    --amount 3 --listen --myip=${TOOLS_SYSTEM_IP} --myport=${BGP_TOOL_PORT} --peerip=${ODL_SYSTEM_IP} --${BGP_TOOL_LOG_LEVEL}
101     Read_And_Fail_If_Prompt_Is_Seen
102
103 Check_Listening_Connection_Is_Not_Established_Yet
104     [Documentation]    See no TCP connection, as both ODL and tool are in listening mode.
105     Check_Speaker_Is_Not_Connected
106
107 Check_For_Empty_Topology_Before_Listening
108     [Documentation]    Sanity check example-ipv4-topology is still empty.
109     [Tags]    critical
110     Verify_That_Topology_Does_Not_Change_From    ${empty_json}    040_Empty.json
111
112 Reconfigure_ODL_To_Initiate_Connection
113     [Documentation]    Replace BGP peer config module, now with initiate-connection set to true.
114     ${template_as_string}=    BuiltIn.Set_Variable    {'NAME': 'example-bgp-peer', 'IP': '${TOOLS_SYSTEM_IP}', 'HOLDTIME': '${HOLDTIME}', 'PEER_PORT': '${BGP_TOOL_PORT}', 'INITIATE': 'true'}
115     ConfigViaRestconf.Put_Xml_Template_Folder_Config_Via_Restconf    ${BGP_VARIABLES_FOLDER}${/}bgp_peer    ${template_as_string}
116
117 Check_Listening_Connection_Is_Established
118     [Documentation]    See TCP (BGP) connection in established state.
119     Check_Speaker_Is_Connected
120
121 Check_Listening_Topology_Is_Filled
122     [Documentation]    See new routes in example-ipv4-topology as a proof that synchronization was correct.
123     [Tags]    critical
124     Wait_For_Topology_To_Change_To    ${filled_json}    050_Filled.json
125
126 Kill_Listening_BGP_Speaker
127     [Documentation]    Abort the Python speaker. Also, attempt to stop failing fast.
128     [Tags]    critical
129     [Setup]    SetupUtils.Setup_Test_With_Logging_And_Without_Fast_Failing
130     BGPSpeaker.Kill_BGP_Speaker
131     FailFast.Do_Not_Fail_Fast_From_Now_On
132     # NOTE: It is still possible to remain failing fast, if both previous and this test have failed.
133     [Teardown]    FailFast.Do_Not_Start_Failing_If_This_Failed
134
135 Check_For_Empty_Topology_After_Listening
136     [Documentation]    Post-condition: Check example-ipv4-topology is empty again.
137     [Tags]    critical
138     Wait_For_Topology_To_Change_To    ${empty_json}    060_Empty.json
139
140 Start_Listening_BGP_Speaker_Case_2
141     [Documentation]    BGP Speaker introduces 2 prefixes in the first update & another 2 prefixes while the very first is withdrawn in 2nd update
142     BGPSpeaker.Start_BGP_Speaker    --amount 3 --listen --myip=${TOOLS_SYSTEM_IP} --myport=${BGP_TOOL_PORT} --peerip=${ODL_SYSTEM_IP} --prefill=2 --insert=2 --withdraw=1 --updates=single --firstprefix=8.0.0.240 --${BGP_TOOL_LOG_LEVEL}
143     Read_And_Fail_If_Prompt_Is_Seen
144
145 Check_Listening_Connection_Is_Established_Case_2
146     [Documentation]    See TCP (BGP) connection in established state.
147     Check_Speaker_Is_Connected
148
149 Check_Listening_Topology_Is_Filled_Case_2
150     [Documentation]    See new routes in example-ipv4-topology as a proof that synchronization was correct.
151     [Tags]    critical
152     Wait_For_Topology_To_Change_To    ${filled_json}    050_Filled.json
153     [Teardown]    Report_Failure_Due_To_Bug    4409
154
155 Kill_Listening_BGP_Speaker_Case_2
156     [Documentation]    Abort the Python speaker. Also, attempt to stop failing fast.
157     [Tags]    critical
158     [Setup]    SetupUtils.Setup_Test_With_Logging_And_Without_Fast_Failing
159     BGPSpeaker.Kill_BGP_Speaker
160     FailFast.Do_Not_Fail_Fast_From_Now_On
161     # NOTE: It is still possible to remain failing fast, if both previous and this test have failed.
162     [Teardown]    FailFast.Do_Not_Start_Failing_If_This_Failed
163
164 Check_For_Empty_Topology_After_Listening_Case_2
165     [Documentation]    Post-condition: Check example-ipv4-topology is empty again.
166     [Tags]    critical
167     Wait_For_Topology_To_Change_To    ${empty_json}    060_Empty.json
168
169 Start_Listening_BGP_Speaker_Case_3
170     [Documentation]    BGP Speaker introduces 3 prefixes while the first one occures again in the withdrawn list (to be ignored bu controller)
171     BGPSpeaker.Start_BGP_Speaker    --amount 2 --listen --myip=${TOOLS_SYSTEM_IP} --myport=${BGP_TOOL_PORT} --peerip=${ODL_SYSTEM_IP} --prefill=0 --insert=3 --withdraw=1 --updates=single --${BGP_TOOL_LOG_LEVEL}
172     Read_And_Fail_If_Prompt_Is_Seen
173
174 Check_Listening_Connection_Is_Established_Case_3
175     [Documentation]    See TCP (BGP) connection in established state.
176     Check_Speaker_Is_Connected
177
178 Check_Listening_Topology_Is_Filled_Case_3
179     [Documentation]    See new routes in example-ipv4-topology as a proof that synchronization was correct.
180     [Tags]    critical
181     Wait_For_Topology_To_Change_To    ${filled_json}    050_Filled.json
182     [Teardown]    Report_Failure_Due_To_Bug    4634
183
184 Kill_Listening_BGP_Speaker_Case_3
185     [Documentation]    Abort the Python speaker. Also, attempt to stop failing fast.
186     [Tags]    critical
187     [Setup]    SetupUtils.Setup_Test_With_Logging_And_Without_Fast_Failing
188     BGPSpeaker.Kill_BGP_Speaker
189     FailFast.Do_Not_Fail_Fast_From_Now_On
190     # NOTE: It is still possible to remain failing fast, if both previous and this test have failed.
191     [Teardown]    FailFast.Do_Not_Start_Failing_If_This_Failed
192
193 Check_For_Empty_Topology_After_Listening_Case_3
194     [Documentation]    Post-condition: Check example-ipv4-topology is empty again.
195     [Tags]    critical
196     Wait_For_Topology_To_Change_To    ${empty_json}    060_Empty.json
197
198 Delete_Bgp_Peer_Configuration
199     [Documentation]    Revert the BGP configuration to the original state: without any configured peers.
200     ${template_as_string}=    BuiltIn.Set_Variable    {'NAME': 'example-bgp-peer'}
201     ConfigViaRestconf.Delete_Xml_Template_Folder_Config_Via_Restconf    ${BGP_VARIABLES_FOLDER}${/}bgp_peer    ${template_as_string}
202     # TODO: Do we need to check something else?
203
204 *** Keywords ***
205 Setup_Everything
206     [Documentation]    SSH-login to mininet machine, create HTTP session,
207     ...    prepare directories for responses, put Python tool to mininet machine, setup imported resources.
208     SetupUtils.Setup_Utils_For_Setup_And_Teardown
209     SSHLibrary.Set_Default_Configuration    prompt=${TOOLS_SYSTEM_PROMPT}
210     SSHLibrary.Open_Connection    ${TOOLS_SYSTEM_IP}
211     Utils.Flexible_Mininet_Login
212     RequestsLibrary.Create_Session    operational    http://${ODL_SYSTEM_IP}:${RESTCONFPORT}${OPERATIONAL_TOPO_API}    auth=${AUTH}
213     # TODO: Do not include slash in ${OPERATIONAL_TOPO_API}, having it typed here is more readable.
214     # TODO: Alternatively, create variable in Variables which starts with http.
215     # Both TODOs would probably need to update every suite relying on current Variables.
216     OperatingSystem.Remove_Directory    ${EXPECTED_RESPONSES_FOLDER}    recursive=True
217     OperatingSystem.Remove_Directory    ${ACTUAL_RESPONSES_FOLDER}    recursive=True
218     # The previous suite may have been using the same directories.
219     OperatingSystem.Create_Directory    ${EXPECTED_RESPONSES_FOLDER}
220     OperatingSystem.Create_Directory    ${ACTUAL_RESPONSES_FOLDER}
221     SSHLibrary.Put_File    ${CURDIR}/../../../../tools/fastbgp/play.py
222     ConfigViaRestconf.Setup_Config_Via_Restconf
223     KarafKeywords.Execute_Controller_Karaf_Command_On_Background    log:set ${CONTROLLER_LOG_LEVEL}
224     KarafKeywords.Execute_Controller_Karaf_Command_On_Background    log:set ${CONTROLLER_BGP_LOG_LEVEL} org.opendaylight.bgpcep
225     KarafKeywords.Execute_Controller_Karaf_Command_On_Background    log:set ${CONTROLLER_BGP_LOG_LEVEL} org.opendaylight.protocol
226
227 Teardown_Everything
228     [Documentation]    Create and Log the diff between expected and actual responses, make sure Python tool was killed.
229     ...    Tear down imported Resources.
230     ${diff}=    OperatingSystem.Run    diff -dur ${EXPECTED_RESPONSES_FOLDER} ${ACTUAL_RESPONSES_FOLDER}
231     BuiltIn.Log    ${diff}
232     KillPythonTool.Search_And_Kill_Remote_Python    'play\.py'
233     ConfigViaRestconf.Teardown_Config_Via_Restconf
234     RequestsLibrary.Delete_All_Sessions
235     SSHLibrary.Close_All_Connections
236
237 Wait_For_Topology_To_Change_To
238     [Arguments]    ${json_topology}    ${filename}    ${timeout}=10s    ${refresh}=1s
239     [Documentation]    Normalize the expected json topology and save it to ${EXPECTED_RESPONSES_FOLDER}.
240     ...    Wait until Compare_Topology matches. ${ACTUAL_RESPONSES_FOLDER} will hold its last result.
241     ${topology_normalized}=    Normalize_And_Save_Expected_Json    ${json_topology}    ${filename}    ${EXPECTED_RESPONSES_FOLDER}
242     BuiltIn.Wait_Until_Keyword_Succeeds    ${timeout}    ${refresh}    Compare_Topology    ${topology_normalized}    ${filename}
243
244 Verify_That_Topology_Does_Not_Change_From
245     [Arguments]    ${json_topology}    ${filename}    ${timeout}=10s    ${refresh}=1s
246     [Documentation]    Normalize the expected json topology and save it to ${EXPECTED_RESPONSES_FOLDER}.
247     ...    Verify that Compare_Topology keeps passing. ${ACTUAL_RESPONSES_FOLDER} will hold its last result.
248     ${topology_normalized}=    Normalize_And_Save_Expected_Json    ${json_topology}    ${filename}    ${EXPECTED_RESPONSES_FOLDER}
249     WaitForFailure.Verify_Keyword_Does_Not_Fail_Within_Timeout    ${timeout}    ${refresh}    Compare_Topology    ${topology_normalized}    ${filename}
250
251 Compare_Topology
252     [Arguments]    ${expected_normalized}    ${filename}
253     [Documentation]    Get current example-ipv4-topology as json, normalize it, save to ${ACTUAL_RESPONSES_FOLDER}.
254     ...    Check that status code is 200, check that normalized jsons match exactly.
255     ${response}=    RequestsLibrary.Get Request    operational    topology/example-ipv4-topology
256     BuiltIn.Log    ${response.status_code}
257     BuiltIn.Log    ${response.text}
258     ${actual_normalized}=    Normalize_And_Save_Expected_Json    ${response.text}    ${filename}    ${ACTUAL_RESPONSES_FOLDER}
259     BuiltIn.Should_Be_Equal_As_Strings    ${response.status_code}    200
260     BuiltIn.Should_Be_Equal    ${actual_normalized}    ${expected_normalized}
261
262 Normalize_And_Save_Expected_Json
263     [Arguments]    ${json_text}    ${filename}    ${directory}
264     [Documentation]    Normalize given json using hsf_json library. Log and save the result to given filename under given directory.
265     ${json_normalized}=    hsf_json.Hsf_Json    ${json_text}
266     BuiltIn.Log    ${json_normalized}
267     OperatingSystem.Create_File    ${directory}${/}${filename}    ${json_normalized}
268     # TODO: Should we prepend .json to the filename? When we detect it is not already prepended?
269     [Return]    ${json_normalized}
270
271 Check_Speaker_Is_Not_Connected
272     [Documentation]    Give it a few tries to see zero established connections.
273     BuiltIn.Wait_Until_Keyword_Succeeds    3s    1s    Check_Number_Of_Speaker_Connections    0
274
275 Check_Speaker_Is_Connected
276     [Documentation]    Give it several tries to see exactly one established connection.
277     BuiltIn.Wait_Until_Keyword_Succeeds    5s    1s    Check_Number_Of_Speaker_Connections    1
278
279 Check_Number_Of_Speaker_Connections
280     [Arguments]    ${howmany}
281     [Documentation]    Run netstat in mininet machine and parse it for number of established connections. Check it is ${howmany}.
282     ${output}=    SSHKeywords.Count_Port_Occurences    17900    ESTABLISHED    python
283     BuiltIn.Should_Be_Equal_As_Strings    ${output}    ${howmany}
284
285 Read_And_Fail_If_Prompt_Is_Seen
286     [Documentation]    Try to read SSH to see prompt, but expect to see no prompt within SSHLibrary's timeout.
287     ${passed}=    BuiltIn.Run_Keyword_And_Return_Status    BuiltIn.Run_Keyword_And_Expect_Error    No match found for '${TOOLS_SYSTEM_PROMPT}' in *.    Read_Text_Before_Prompt
288     BuiltIn.Return_From_Keyword_If    ${passed}
289     BGPSpeaker.Dump_BGP_Speaker_Logs
290     Builtin.Fail    The prompt was seen but it was not expected yet
291
292 Read_Text_Before_Prompt
293     [Documentation]    Log text gathered by SSHLibrary.Read_Until_Prompt.
294     ...    This needs to be a separate keyword just because how Read_And_Fail_If_Prompt_Is_Seen is implemented.
295     ${text}=    SSHLibrary.Read_Until_Prompt
296     BuiltIn.Log    ${text}