fixeria has uploaded this change for review. ( 
https://gerrit.osmocom.org/c/osmo-ttcn3-hacks/+/42360?usp=email )


Change subject: s1gw: add tests for MME registry REST procedures
......................................................................

s1gw: add tests for MME registry REST procedures

Add three test cases exercising the S1GW REST interface for MME pool
management.  The REST TCs are gated on the mp_rest_enable module
parameter in the control block.

TC_rest_mme_list: query the MME pool list via REST and verify it
matches the three static entries from the 'mme_pool' section in
osmo-s1gw.config (mme0/mme1/mme2 with their respective addresses).

TC_rest_mme_add_del: add a new MME entry at runtime via REST, verify
it appears in both the list and individual GET responses, then delete
it and confirm it is gone.

TC_rest_mme_del_fallback: delete mme0 from the pool at runtime and
verify that a connecting eNB is routed directly to mme1, skipping the
deleted entry.  The pool is restored to its original state afterwards
via f_REST_mme_pool_restore().

Also add:
* {ts,tr}_MmeItem templates to S1GW_REST_Types.ttcn
* f_REST_mme_find(): returns the integer index of a named entry in a
  MmeList, or -1 if not found; used for both presence and absence checks
* f_REST_mme_pool_restore(): deletes all current entries and re-adds
  mme0/mme1/mme2 in original order to keep pool state predictable
  across test cases

Change-Id: I260bc987ab8ae0ecb547d0b69b261fd97c5c9c23
Related: SYS#7052
---
M s1gw/S1GW_REST_Types.ttcn
M s1gw/S1GW_Tests.ttcn
M s1gw/expected-results.xml
3 files changed, 198 insertions(+), 1 deletion(-)



  git pull ssh://gerrit.osmocom.org:29418/osmo-ttcn3-hacks 
refs/changes/60/42360/1

diff --git a/s1gw/S1GW_REST_Types.ttcn b/s1gw/S1GW_REST_Types.ttcn
index f182ae9..696df3d 100644
--- a/s1gw/S1GW_REST_Types.ttcn
+++ b/s1gw/S1GW_REST_Types.ttcn
@@ -157,4 +157,30 @@
 external function dec_ErabItem(in octetstring data) return ErabItem
        with { extension "prototype(convert) decode(JSON)" }

+
+template (value) MmeItem
+ts_MmeItem(template (value) charstring name,
+          template (value) charstring raddr,
+          template (omit) charstring laddr := omit,
+          template (omit) Port rport := omit,
+          template (omit) TacList tac_list := omit) := {
+       name := name,
+       laddr := laddr,
+       raddr := raddr,
+       rport := rport,
+       tac_list := tac_list
+}
+template (present) MmeItem
+tr_MmeItem(template (present) charstring name := ?,
+          template (present) charstring raddr := ?,
+          template charstring laddr := *,
+          template Port rport := *,
+          template TacList tac_list := *) := {
+       name := name,
+       laddr := laddr,
+       raddr := raddr,
+       rport := rport,
+       tac_list := tac_list
+}
+
 } with { encode "JSON" }
diff --git a/s1gw/S1GW_Tests.ttcn b/s1gw/S1GW_Tests.ttcn
index d870be8..f2af12a 100644
--- a/s1gw/S1GW_Tests.ttcn
+++ b/s1gw/S1GW_Tests.ttcn
@@ -1200,6 +1200,167 @@
                       { S1APSRV_SETUP_ACCEPT });
 }

+
+/* Find an MME entry in the list by name; return its index, or -1 if not found 
*/
+private function f_REST_mme_find(MmeList mmes, charstring name) return integer 
{
+       for (var integer i := 0; i < lengthof(mmes); i := i + 1) {
+               if (mmes[i].name == name) {
+                       return i;
+               }
+       }
+       return -1;
+}
+
+/* Restore the MME pool to its original state: delete all current entries and
+ * re-add the three static pool entries (mme0/mme1/mme2) in their original 
order. */
+private function f_REST_mme_pool_restore() runs on test_CT {
+       var MmeList mmes := f_REST_MmeList();
+       for (var integer i := 0; i < lengthof(mmes); i := i + 1) {
+               f_REST_MmeDelete({ name := "name:" & mmes[i].name });
+       }
+       for (var integer i := 0; i < 3; i := i + 1) {
+               f_REST_MmeAdd(valueof(ts_MmeItem(name := "mme" & int2str(i),
+                                                raddr := f_mme_ip(i))));
+       }
+}
+
+/* REST test: verify the configured MME pool is correctly reflected via REST */
+testcase TC_rest_mme_list() runs on test_CT {
+       var template (present) MmeList tr_mmes;
+       var MmeList mmes;
+
+       f_init(s1apsrv_start := false, upf_start := false);
+
+       /* this resembles the 'mme_pool' section in osmo-s1gw.config */
+       for (var integer i := 0; i < 3; i := i + 1) {
+               tr_mmes[i] := tr_MmeItem(name := "mme" & int2str(i),
+                                        raddr := f_mme_ip(i),
+                                        laddr := "any",
+                                        rport := 36412,
+                                        tac_list := { });
+       }
+
+       mmes := f_REST_MmeList();
+       if (not match(mmes, tr_mmes)) {
+               setverdict(fail, "Got unexpected MmeList: ", mmes);
+       }
+
+       setverdict(pass);
+}
+
+/* REST test: add an MME to the pool, verify it appears, then delete it */
+testcase TC_rest_mme_add_del() runs on test_CT {
+       var MmeList mmes;
+       var MmeItem mme;
+       var integer idx;
+
+       var template (value) MmeItem ts_mme_test := ts_MmeItem(name := 
"mme-test",
+                                                              raddr := 
f_mme_ip(9));
+       var template (present) MmeItem tr_mme_test := tr_MmeItem(name := 
"mme-test",
+                                                                raddr := 
f_mme_ip(9),
+                                                                laddr := "any",
+                                                                rport := 36412,
+                                                                tac_list := { 
});
+
+       f_init(s1apsrv_start := false, upf_start := false);
+
+       /* add the new entry and verify it appears in the list */
+       if (not f_REST_MmeAdd(valueof(ts_mme_test))) {
+               setverdict(fail, "Failed to add mme-test via REST");
+               Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
+       }
+       mmes := f_REST_MmeList();
+       if (lengthof(mmes) != 4) {
+               setverdict(fail, "Expected 4 MMEs after add, got ", 
lengthof(mmes));
+               Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
+       }
+       idx := f_REST_mme_find(mmes, "mme-test");
+       if (idx == -1) {
+               setverdict(fail, "mme-test not found in MmeList after add");
+               Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
+       }
+       if (not match(mmes[idx], tr_mme_test)) {
+               setverdict(fail, "mme-test does not match: ", mmes[idx]);
+               Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
+       }
+
+       /* also verify via individual GET */
+       mme := f_REST_MmeInfo({ name := "name:mme-test" });
+       if (not match(mme, tr_mme_test)) {
+               setverdict(fail, "mme-test does not match: ", mme);
+               Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
+       }
+
+       /* delete the entry and verify it's gone */
+       if (not f_REST_MmeDelete({ name := "name:mme-test" })) {
+               setverdict(fail, "Failed to delete mme-test via REST");
+               Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
+       }
+       mmes := f_REST_MmeList();
+       if (lengthof(mmes) != 3) {
+               setverdict(fail, "Expected 3 MMEs after delete, got ", 
lengthof(mmes));
+               Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
+       }
+       if (f_REST_mme_find(mmes, "mme-test") != -1) {
+               setverdict(fail, "mme-test still present in MmeList after 
delete");
+               Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
+       }
+
+       setverdict(pass);
+}
+
+/* ConnHdlr body for TC_rest_mme_del_fallback: connect and complete S1 setup 
via pool */
+private function f_TC_rest_pool_connect_accept(charstring id) runs on ConnHdlr 
{
+       f_ConnHdlr_s1ap_connect(mp_enb_bind_ip, mp_s1gw_enb_ip);
+       f_ConnHdlr_s1ap_setup_pool(g_pars.pool_srvs, g_pars.pool_behaviors);
+       f_sleep(0.5);
+       f_ConnHdlr_s1ap_disconnect();
+       f_ConnHdlr_s1ap_unregister_from(g_pars.genb_id, g_s1ap_server);
+}
+
+/* REST test: delete an MME from the pool at runtime; eNB must fall back to the
+ * next available MME without attempting to connect to the deleted entry. */
+testcase TC_rest_mme_del_fallback() runs on test_CT {
+       var ConnHdlrPars pars;
+       var ConnHdlr vc_conn;
+       var MmeList mmes;
+
+       /* start 2 S1AP servers: server[0][email protected], 
server[1][email protected] */
+       f_init(num_mmes := 2);
+
+       /* delete mme0: effective pool becomes [mme1, mme2] */
+       if (not f_REST_MmeDelete({ name := "name:mme0" })) {
+               setverdict(fail, "Failed to delete mme0 via REST");
+               Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
+       }
+       mmes := f_REST_MmeList();
+       if (lengthof(mmes) != 2) {
+               setverdict(fail, "Expected 2 MMEs after deleting mme0, got ", 
lengthof(mmes));
+               Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
+       }
+       if (f_REST_mme_find(mmes, "mme0") != -1) {
+               setverdict(fail, "mme0 still present in MmeList after delete");
+               Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
+       }
+
+       /* eNB connects: S1GW must select mme1 (server[1]@127.0.2.11) directly 
*/
+       pars := valueof(t_ConnHdlrPars);
+       pars.pool_srvs := { vc_S1APSRVs[1] };
+       pars.pool_behaviors := { S1APSRV_SETUP_ACCEPT };
+       vc_conn := f_ConnHdlr_spawn(refers(f_TC_rest_pool_connect_accept), 
pars);
+       vc_conn.done;
+
+       /* restore original pool state (mme0/mme1/mme2 in order) for subsequent 
tests */
+       f_REST_mme_pool_restore();
+       mmes := f_REST_MmeList();
+       if (lengthof(mmes) != 3) {
+               setverdict(fail, "Expected 3 MMEs after pool restore, got ", 
lengthof(mmes));
+               Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
+       }
+
+       setverdict(pass);
+}
+
 control {
        execute( TC_setup() );
        execute( TC_setup_multi() );
@@ -1241,6 +1402,13 @@
        execute( TC_mme_pool_all_reject() );
        execute( TC_mme_pool_enb_disc_wait_s1setup_req() );
        execute( TC_mme_pool_enb_disc_wait_s1setup_rsp() );
+
+       /* REST interface TCs */
+       if (mp_rest_enable) {
+               execute( TC_rest_mme_list() );
+               execute( TC_rest_mme_add_del() );
+               execute( TC_rest_mme_del_fallback() );
+       }
 }

 }
diff --git a/s1gw/expected-results.xml b/s1gw/expected-results.xml
index 0769764..b2b6cdb 100644
--- a/s1gw/expected-results.xml
+++ b/s1gw/expected-results.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0"?>
-<testsuite name='S1GW_Tests' tests='38' failures='0' errors='0' skipped='0' 
inconc='0' time='MASKED'>
+<testsuite name='S1GW_Tests' tests='41' failures='0' errors='0' skipped='0' 
inconc='0' time='MASKED'>
   <testcase classname='S1GW_Tests' name='TC_setup' time='MASKED'/>
   <testcase classname='S1GW_Tests' name='TC_setup_multi' time='MASKED'/>
   <testcase classname='S1GW_Tests' name='TC_conn_term_by_mme' time='MASKED'/>
@@ -40,4 +40,7 @@
   <testcase classname='S1GW_Tests' name='TC_mme_pool_all_reject' 
time='MASKED'/>
   <testcase classname='S1GW_Tests' 
name='TC_mme_pool_enb_disc_wait_s1setup_req' time='MASKED'/>
   <testcase classname='S1GW_Tests' 
name='TC_mme_pool_enb_disc_wait_s1setup_rsp' time='MASKED'/>
+  <testcase classname='S1GW_Tests' name='TC_rest_mme_list' time='MASKED'/>
+  <testcase classname='S1GW_Tests' name='TC_rest_mme_add_del' time='MASKED'/>
+  <testcase classname='S1GW_Tests' name='TC_rest_mme_del_fallback' 
time='MASKED'/>
 </testsuite>

--
To view, visit https://gerrit.osmocom.org/c/osmo-ttcn3-hacks/+/42360?usp=email
To unsubscribe, or for help writing mail filters, visit 
https://gerrit.osmocom.org/settings?usp=email

Gerrit-MessageType: newchange
Gerrit-Project: osmo-ttcn3-hacks
Gerrit-Branch: master
Gerrit-Change-Id: I260bc987ab8ae0ecb547d0b69b261fd97c5c9c23
Gerrit-Change-Number: 42360
Gerrit-PatchSet: 1
Gerrit-Owner: fixeria <[email protected]>

Reply via email to