pespin has uploaded this change for review.
tests/gmm: Introduce skeleton for gmm_prim_network tests
A new skeleton to add tests for the network (SGSN) mode is added.
Related: OS#5852
Change-Id: I832f16f598f49c18455531fac75367376a3065e6
---
M tests/gmm/Makefile.am
M tests/gmm/gmm_prim_ms_test.c
A tests/gmm/gmm_prim_network_test.c
A tests/gmm/gmm_prim_network_test.err
A tests/gmm/gmm_prim_network_test.ok
A tests/gmm/gmm_prim_test.h
M tests/testsuite.at
7 files changed, 366 insertions(+), 40 deletions(-)
git pull ssh://gerrit.osmocom.org:29418/libosmo-gprs refs/changes/26/37726/1
diff --git a/tests/gmm/Makefile.am b/tests/gmm/Makefile.am
index c84c879..ad565a6 100644
--- a/tests/gmm/Makefile.am
+++ b/tests/gmm/Makefile.am
@@ -15,6 +15,7 @@
check_PROGRAMS = \
gmm_misc_test \
gmm_prim_ms_test \
+ gmm_prim_network_test \
$(NULL)
EXTRA_DIST = \
@@ -22,6 +23,8 @@
gmm_misc_test.ok \
gmm_prim_ms_test.err \
gmm_prim_ms_test.ok \
+ gmm_prim_network_test.err \
+ gmm_prim_network_test.ok \
$(NULL)
# libosmo-gprs-gmm.a is used below to access non-exported private symbols used in the test:
@@ -53,3 +56,20 @@
-Wl,--wrap=osmo_get_rand_id \
-no-install \
$(NULL)
+
+# libosmo-gprs-llc.a is used below to access non-exported private symbols used in the test:
+# libosmo-gprs-rlcmac.a is used below to access non-exported private symbols used in the test:
+gmm_prim_network_test_SOURCES = gmm_prim_network_test.c
+gmm_prim_network_test_LDADD = \
+ $(top_builddir)/src/gmm/libosmo-gprs-gmm.la \
+ $(top_builddir)/src/llc/.libs/libosmo-gprs-llc.a \
+ $(top_builddir)/src/rlcmac/.libs/libosmo-gprs-rlcmac.a \
+ $(top_builddir)/src/csn1/libosmo-csn1.la \
+ $(LIBOSMOCORE_LIBS) \
+ $(LIBOSMOGSM_LIBS) \
+ $(NULL)
+
+gmm_prim_network_test_LDFLAGS = \
+ -Wl,--wrap=osmo_get_rand_id \
+ -no-install \
+ $(NULL)
diff --git a/tests/gmm/gmm_prim_ms_test.c b/tests/gmm/gmm_prim_ms_test.c
index c33bddc..dcbd31a 100644
--- a/tests/gmm/gmm_prim_ms_test.c
+++ b/tests/gmm/gmm_prim_ms_test.c
@@ -1,4 +1,4 @@
-/* gmm_prim tests
+/* gmm_prim tests (MS side)
*
* (C) 2023 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de>
* Author: Pau espin Pedrol <pespin@sysmocom.de>
@@ -28,8 +28,6 @@
#include <osmocom/core/utils.h>
#include <osmocom/core/fsm.h>
#include <osmocom/core/msgb.h>
-#include <osmocom/core/timer.h>
-#include <osmocom/core/timer_compat.h>
#include <osmocom/core/select.h>
#include <osmocom/gprs/rlcmac/rlcmac_private.h>
@@ -39,6 +37,8 @@
#include <osmocom/gprs/gmm/gmm_prim.h>
#include <osmocom/gprs/gmm/gmm_pdu.h>
+#include "gmm_prim_test.h"
+
static void *tall_ctx = NULL;
/*
@@ -189,43 +189,6 @@
return 0;
}
-#define clock_debug(fmt, args...) \
- do { \
- struct timespec ts; \
- struct timeval tv; \
- osmo_clock_gettime(CLOCK_MONOTONIC, &ts); \
- osmo_gettimeofday(&tv, NULL); \
- fprintf(stdout, "sys={%lu.%06lu}, mono={%lu.%06lu}: " fmt "\n", \
- tv.tv_sec, tv.tv_usec, ts.tv_sec, ts.tv_nsec/1000, ##args); \
- } while (0)
-
-static void clock_override_enable(bool enable)
-{
- osmo_gettimeofday_override = enable;
- osmo_clock_override_enable(CLOCK_MONOTONIC, enable);
-}
-
-static void clock_override_set(long sec, long usec)
-{
- struct timespec *mono;
- osmo_gettimeofday_override_time.tv_sec = sec;
- osmo_gettimeofday_override_time.tv_usec = usec;
- mono = osmo_clock_override_gettimespec(CLOCK_MONOTONIC);
- mono->tv_sec = sec;
- mono->tv_nsec = usec*1000;
-
- clock_debug("clock_override_set");
-}
-
-static void clock_override_add_debug(long sec, long usec, bool dbg)
-{
- osmo_gettimeofday_override_add(sec, usec);
- osmo_clock_override_add(CLOCK_MONOTONIC, sec, usec*1000);
- if (dbg)
- clock_debug("clock_override_add");
-}
-#define clock_override_add(sec, usec) clock_override_add_debug(sec, usec, true)
-
int test_gmm_prim_up_cb(struct osmo_gprs_gmm_prim *gmm_prim, void *user_data)
{
const char *pdu_name = osmo_gprs_gmm_prim_name(gmm_prim);
diff --git a/tests/gmm/gmm_prim_network_test.c b/tests/gmm/gmm_prim_network_test.c
new file mode 100644
index 0000000..6e8a053
--- /dev/null
+++ b/tests/gmm/gmm_prim_network_test.c
@@ -0,0 +1,276 @@
+/* gmm_prim tests (network side)
+ *
+ * (C) 2023 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de>
+ * Author: Pau espin Pedrol <pespin@sysmocom.de>
+ *
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <stdint.h>
+#include <stdio.h>
+
+#include <osmocom/core/application.h>
+#include <osmocom/core/logging.h>
+#include <osmocom/core/utils.h>
+#include <osmocom/core/fsm.h>
+#include <osmocom/core/msgb.h>
+#include <osmocom/core/select.h>
+
+#include <osmocom/gprs/rlcmac/rlcmac_private.h>
+#include <osmocom/gprs/llc/llc_prim.h>
+#include <osmocom/gprs/llc/llc_private.h>
+#include <osmocom/gprs/gmm/gmm.h>
+#include <osmocom/gprs/gmm/gmm_prim.h>
+#include <osmocom/gprs/gmm/gmm_pdu.h>
+
+#include "gmm_prim_test.h"
+
+static void *tall_ctx = NULL;
+
+static uint8_t pdu_gmm_att_req[] = { /* TODO: provide good hexstring, this comes from a att_accept... */
+0x08, 0x02, 0x01, 0x2a, 0x44, 0x32, 0xf4, 0x07, 0x00, 0x05, 0x00, 0x17, 0x16, 0x18, 0x05, 0xf4,
+0xea, 0x71, 0x1b, 0x41
+};
+
+static uint8_t pdu_gmm_id_resp[] = { /* TODO: provide GMM Identification Response here */
+};
+
+/* override, requires '-Wl,--wrap=osmo_get_rand_id' */
+int __real_osmo_get_rand_id(uint8_t *data, size_t len);
+int __wrap_osmo_get_rand_id(uint8_t *data, size_t len)
+{
+ memset(data, 0x00, len);
+ return 0;
+}
+
+int test_gmm_prim_up_cb(struct osmo_gprs_gmm_prim *gmm_prim, void *user_data)
+{
+ const char *pdu_name = osmo_gprs_gmm_prim_name(gmm_prim);
+ struct osmo_gprs_gmm_prim *gmm_prim_tx;
+ int rc;
+
+ switch (gmm_prim->oph.sap) {
+ case OSMO_GPRS_GMM_SAP_GMMREG:
+ switch (OSMO_PRIM_HDR(&gmm_prim->oph)) {
+ case OSMO_PRIM(OSMO_GPRS_GMM_GMMREG_ATTACH, PRIM_OP_CONFIRM):
+ if (gmm_prim->gmmreg.attach_cnf.accepted) {
+ printf("%s(): Rx %s accepted=%u allocated_ptmsi=0x%08x allocated_ptmsi_sig=0x%06x allocated_tlli=0x%08x\n", __func__, pdu_name,
+ gmm_prim->gmmreg.attach_cnf.accepted,
+ gmm_prim->gmmreg.attach_cnf.acc.allocated_ptmsi,
+ gmm_prim->gmmreg.attach_cnf.acc.allocated_ptmsi_sig,
+ gmm_prim->gmmreg.attach_cnf.acc.allocated_tlli);
+ } else {
+ printf("%s(): Rx %s accepted=%u rej_cause=%u\n", __func__, pdu_name,
+ gmm_prim->gmmreg.attach_cnf.accepted,
+ gmm_prim->gmmreg.attach_cnf.rej.cause);
+ }
+ break;
+ case OSMO_PRIM(OSMO_GPRS_GMM_GMMREG_DETACH, PRIM_OP_CONFIRM):
+ printf("%s(): Rx %s detach_type='%s'\n", __func__, pdu_name,
+ osmo_gprs_gmm_detach_ms_type_name(gmm_prim->gmmreg.detach_cnf.detach_type));
+ break;
+ case OSMO_PRIM(OSMO_GPRS_GMM_GMMREG_SIM_AUTH, PRIM_OP_INDICATION):
+ printf("%s(): Rx %s ac_ref_nr=%u key_seq=%u rand=%s\n",
+ __func__, pdu_name,
+ gmm_prim->gmmreg.sim_auth_ind.ac_ref_nr,
+ gmm_prim->gmmreg.sim_auth_ind.key_seq,
+ osmo_hexdump(gmm_prim->gmmreg.sim_auth_ind.rand,
+ sizeof(gmm_prim->gmmreg.sim_auth_ind.rand)));
+ /* Emulate SIM, asnwer SRES=0xacacacac, Kc=bdbdbd... */
+ gmm_prim_tx = osmo_gprs_gmm_prim_alloc_gmmreg_sim_auth_rsp();
+ OSMO_ASSERT(gmm_prim_tx);
+ gmm_prim_tx->gmmreg.sim_auth_rsp.ac_ref_nr = gmm_prim->gmmreg.sim_auth_ind.ac_ref_nr;
+ gmm_prim_tx->gmmreg.sim_auth_rsp.key_seq = gmm_prim->gmmreg.sim_auth_ind.key_seq;
+ memcpy(gmm_prim_tx->gmmreg.sim_auth_rsp.rand, gmm_prim->gmmreg.sim_auth_ind.rand,
+ sizeof(gmm_prim_tx->gmmreg.sim_auth_rsp.rand));
+ memset(gmm_prim_tx->gmmreg.sim_auth_rsp.sres, 0xac,
+ sizeof(gmm_prim_tx->gmmreg.sim_auth_rsp.sres));
+ memset(gmm_prim_tx->gmmreg.sim_auth_rsp.kc, 0xbd,
+ sizeof(gmm_prim_tx->gmmreg.sim_auth_rsp.kc));
+ rc = osmo_gprs_gmm_prim_upper_down(gmm_prim_tx);
+ OSMO_ASSERT(rc == 0);
+ break;
+ default:
+ printf("%s(): Unexpected Rx %s\n", __func__, pdu_name);
+ OSMO_ASSERT(0)
+ }
+ break;
+ case OSMO_GPRS_GMM_SAP_GMMSM:
+ switch (OSMO_PRIM_HDR(&gmm_prim->oph)) {
+ case OSMO_PRIM(OSMO_GPRS_GMM_GMMSM_ESTABLISH, PRIM_OP_CONFIRM):
+ if (gmm_prim->gmmsm.establish_cnf.accepted)
+ printf("%s(): Rx %s sess_id=%u accepted\n", __func__, pdu_name,
+ gmm_prim->gmmsm.sess_id);
+ else
+ printf("%s(): Rx %s sess_id=%u rejected cause=%u\n", __func__, pdu_name,
+ gmm_prim->gmmsm.sess_id,
+ gmm_prim->gmmsm.establish_cnf.rej.cause);
+ break;
+ case OSMO_PRIM(OSMO_GPRS_GMM_GMMSM_UNITDATA, PRIM_OP_INDICATION):
+ printf("%s(): Rx %s sess_id=%u sm_pdu=%s\n", __func__, pdu_name,
+ gmm_prim->gmmsm.sess_id,
+ osmo_hexdump(gmm_prim->gmmsm.unitdata_ind.smpdu,
+ gmm_prim->gmmsm.unitdata_ind.smpdu_len));
+ break;
+ case OSMO_PRIM(OSMO_GPRS_GMM_GMMSM_RELEASE, PRIM_OP_INDICATION):
+ printf("%s(): Rx %s sess_id=%u\n", __func__, pdu_name,
+ gmm_prim->gmmsm.sess_id);
+ break;
+ case OSMO_PRIM(OSMO_GPRS_GMM_GMMSM_MODIFY, PRIM_OP_INDICATION):
+ printf("%s(): Rx %s sess_id=%u allocated_ptmsi=0x%08x allocated_ptmsi_sig=0x%06x allocated_tlli=0x%08x\n", __func__, pdu_name,
+ gmm_prim->gmmsm.sess_id,
+ gmm_prim->gmmsm.modify_ind.allocated_ptmsi,
+ gmm_prim->gmmsm.modify_ind.allocated_ptmsi_sig,
+ gmm_prim->gmmsm.modify_ind.allocated_tlli);
+ break;
+ default:
+ printf("%s(): Unexpected Rx %s\n", __func__, pdu_name);
+ OSMO_ASSERT(0)
+ }
+ break;
+ default:
+ printf("%s(): Unexpected Rx %s\n", __func__, pdu_name);
+ OSMO_ASSERT(0);
+ }
+ return 0;
+}
+
+int test_gmm_prim_down_cb(struct osmo_gprs_gmm_prim *gmm_prim, void *user_data)
+{
+ const char *pdu_name = osmo_gprs_gmm_prim_name(gmm_prim);
+
+ switch (gmm_prim->oph.sap) {
+ case OSMO_GPRS_GMM_SAP_GMMBSSGP:
+ switch (OSMO_PRIM_HDR(&gmm_prim->oph)) {
+ case OSMO_PRIM(OSMO_GPRS_GMM_GMMBSSGP_PAGING, PRIM_OP_REQUEST):
+ case OSMO_PRIM(OSMO_GPRS_GMM_GMMBSSGP_RA_CAPABILITY, PRIM_OP_REQUEST):
+ case OSMO_PRIM(OSMO_GPRS_GMM_GMMBSSGP_RA_CAPABILITY_UPDATE, PRIM_OP_RESPONSE):
+ case OSMO_PRIM(OSMO_GPRS_GMM_GMMBSSGP_MS_REGISTRATION_ENQUIRY, PRIM_OP_RESPONSE):
+ printf("%s(): Rx %s\n", __func__, pdu_name);
+ break;
+ }
+ break;
+ default:
+ printf("%s(): Unexpected Rx %s\n", __func__, pdu_name);
+ OSMO_ASSERT(0);
+ }
+ return 0;
+}
+
+int test_gmm_prim_llc_down_cb(struct osmo_gprs_llc_prim *llc_prim, void *user_data)
+{
+ const char *pdu_name = osmo_gprs_llc_prim_name(llc_prim);
+ struct osmo_gprs_gmm_prim *gmm_prim_tx;
+
+ switch (llc_prim->oph.sap) {
+ case OSMO_GPRS_LLC_SAP_LLGMM:
+ switch (OSMO_PRIM_HDR(&llc_prim->oph)) {
+ case OSMO_PRIM(OSMO_GPRS_LLC_LLGMM_ASSIGN, PRIM_OP_REQUEST):
+ printf("%s(): Rx %s old_TLLI=0x%08x new_TLLI=0x%08x\n",
+ __func__, pdu_name,
+ llc_prim->llgmm.tlli, llc_prim->llgmm.assign_req.tlli_new);
+ break;
+ default:
+ printf("%s(): Rx %s TLLI=0x%08x\n", __func__, pdu_name, llc_prim->llgmm.tlli);
+ }
+ break;
+ case OSMO_GPRS_LLC_SAP_LL:
+ printf("%s(): Rx %s TLLI=0x%08x SAPI=%s l3=[%s]\n", __func__, pdu_name,
+ llc_prim->ll.tlli, osmo_gprs_llc_sapi_name(llc_prim->ll.sapi),
+ osmo_hexdump(llc_prim->ll.l3_pdu, llc_prim->ll.l3_pdu_len));
+ switch (OSMO_PRIM_HDR(&llc_prim->oph)) {
+ case OSMO_PRIM(OSMO_GPRS_LLC_LL_UNITDATA, PRIM_OP_REQUEST):
+ /* Immediately notify GMM that it was transmitted over the air: */
+ gmm_prim_tx = (struct osmo_gprs_gmm_prim *)gprs_rlcmac_prim_alloc_gmmrr_llc_transmitted_ind(llc_prim->ll.tlli);
+ gmm_prim_tx->oph.sap = OSMO_GPRS_GMM_SAP_GMMRR;
+ gmm_prim_tx->oph.primitive = OSMO_GPRS_GMM_GMMRR_LLC_TRANSMITTED;
+ osmo_gprs_gmm_prim_lower_up(gmm_prim_tx);
+ break;
+ }
+ break;
+ default:
+ printf("%s(): Unexpected Rx %s\n", __func__, pdu_name);
+ OSMO_ASSERT(0);
+ }
+ return 0;
+}
+
+/* Test explicit GPRS attach through GMMREG, TS 24.007 Annex C.1 */
+static void test_gmm_prim_ms_gmmreg(void)
+{
+ //struct osmo_gprs_gmm_prim *gmm_prim;
+ struct osmo_gprs_llc_prim *llc_prim;
+ int rc;
+ uint32_t rand_tlli = 0x80001234;
+
+ printf("==== %s() [start] ====\n", __func__);
+
+ clock_override_set(0, 0);
+
+ rc = osmo_gprs_gmm_init(OSMO_GPRS_GMM_LOCATION_NETWORK);
+ OSMO_ASSERT(rc == 0);
+
+ osmo_gprs_gmm_prim_set_up_cb(test_gmm_prim_up_cb, NULL);
+ osmo_gprs_gmm_prim_set_down_cb(test_gmm_prim_down_cb, NULL);
+ osmo_gprs_gmm_prim_set_llc_down_cb(test_gmm_prim_llc_down_cb, NULL);
+
+ /* MS sends GMM Attach Req */
+ llc_prim = gprs_llc_prim_alloc_ll_unitdata_ind(rand_tlli, OSMO_GPRS_LLC_SAPI_GMM, (uint8_t *)pdu_gmm_att_req, sizeof(pdu_gmm_att_req));
+ OSMO_ASSERT(llc_prim);
+ rc = osmo_gprs_gmm_prim_llc_lower_up(llc_prim);
+ /* TODO: implement this primitive!
+ * OSMO_ASSERT(rc == 0); */
+ /* As a result, Network answers with GMM Identification Request. */
+
+ /* MS sends GMM Identification response */
+ llc_prim = gprs_llc_prim_alloc_ll_unitdata_ind(rand_tlli, OSMO_GPRS_LLC_SAPI_GMM, (uint8_t *)pdu_gmm_id_resp, sizeof(pdu_gmm_id_resp));
+ OSMO_ASSERT(llc_prim);
+ rc = osmo_gprs_gmm_prim_llc_lower_up(llc_prim);
+ /* TODO: implement this primitive!
+ * OSMO_ASSERT(rc == 0); */
+
+ /* ... */
+
+ printf("==== %s() [end] ====\n", __func__);
+}
+
+static const struct log_info_cat test_log_categories[] = { };
+static const struct log_info test_log_info = {
+ .cat = test_log_categories,
+ .num_cat = ARRAY_SIZE(test_log_categories),
+};
+
+int main(int argc, char *argv[])
+{
+ tall_ctx = talloc_named_const(NULL, 1, __FILE__);
+
+ osmo_init_logging2(tall_ctx, &test_log_info);
+ log_parse_category_mask(osmo_stderr_target, "DLGLOBAL,1:");
+ osmo_fsm_log_addr(false);
+
+ log_set_print_filename2(osmo_stderr_target, LOG_FILENAME_NONE);
+ log_set_print_category_hex(osmo_stderr_target, 0);
+ log_set_print_category(osmo_stderr_target, 1);
+ log_set_print_level(osmo_stderr_target, 1);
+ log_set_use_color(osmo_stderr_target, 0);
+
+ clock_override_enable(true);
+
+ test_gmm_prim_ms_gmmreg();
+
+ talloc_free(tall_ctx);
+}
diff --git a/tests/gmm/gmm_prim_network_test.err b/tests/gmm/gmm_prim_network_test.err
new file mode 100644
index 0000000..e73f215
--- /dev/null
+++ b/tests/gmm/gmm_prim_network_test.err
@@ -0,0 +1,4 @@
+DLGLOBAL INFO Rx from lower layers: LL-UNITDATA.indication
+DLGLOBAL NOTICE Rx LL-UNITDATA.indication: Unknown TLLI 0x80001234
+DLGLOBAL INFO Rx from lower layers: LL-UNITDATA.indication
+DLGLOBAL NOTICE Rx LL-UNITDATA.indication: Unknown TLLI 0x80001234
diff --git a/tests/gmm/gmm_prim_network_test.ok b/tests/gmm/gmm_prim_network_test.ok
new file mode 100644
index 0000000..a26ff56
--- /dev/null
+++ b/tests/gmm/gmm_prim_network_test.ok
@@ -0,0 +1,3 @@
+==== test_gmm_prim_ms_gmmreg() [start] ====
+sys={0.000000}, mono={0.000000}: clock_override_set
+==== test_gmm_prim_ms_gmmreg() [end] ====
diff --git a/tests/gmm/gmm_prim_test.h b/tests/gmm/gmm_prim_test.h
new file mode 100644
index 0000000..1e231b1
--- /dev/null
+++ b/tests/gmm/gmm_prim_test.h
@@ -0,0 +1,41 @@
+#pragma once
+
+#include <osmocom/core/timer.h>
+#include <osmocom/core/timer_compat.h>
+
+#define clock_debug(fmt, args...) \
+ do { \
+ struct timespec ts; \
+ struct timeval tv; \
+ osmo_clock_gettime(CLOCK_MONOTONIC, &ts); \
+ osmo_gettimeofday(&tv, NULL); \
+ fprintf(stdout, "sys={%lu.%06lu}, mono={%lu.%06lu}: " fmt "\n", \
+ tv.tv_sec, tv.tv_usec, ts.tv_sec, ts.tv_nsec/1000, ##args); \
+ } while (0)
+
+static void clock_override_enable(bool enable)
+{
+ osmo_gettimeofday_override = enable;
+ osmo_clock_override_enable(CLOCK_MONOTONIC, enable);
+}
+
+static void clock_override_set(long sec, long usec)
+{
+ struct timespec *mono;
+ osmo_gettimeofday_override_time.tv_sec = sec;
+ osmo_gettimeofday_override_time.tv_usec = usec;
+ mono = osmo_clock_override_gettimespec(CLOCK_MONOTONIC);
+ mono->tv_sec = sec;
+ mono->tv_nsec = usec*1000;
+
+ clock_debug("clock_override_set");
+}
+
+static inline void clock_override_add_debug(long sec, long usec, bool dbg)
+{
+ osmo_gettimeofday_override_add(sec, usec);
+ osmo_clock_override_add(CLOCK_MONOTONIC, sec, usec*1000);
+ if (dbg)
+ clock_debug("clock_override_add");
+}
+#define clock_override_add(sec, usec) clock_override_add_debug(sec, usec, true)
diff --git a/tests/testsuite.at b/tests/testsuite.at
index 3b5c326..e819a8d 100644
--- a/tests/testsuite.at
+++ b/tests/testsuite.at
@@ -15,6 +15,13 @@
AT_CHECK([$abs_top_builddir/tests/gmm/gmm_prim_ms_test], [0], [expout], [experr])
AT_CLEANUP
+AT_SETUP([gmm/gmm_prim_network])
+AT_KEYWORDS([gmm gmm_prim_network])
+cat $abs_srcdir/gmm/gmm_prim_network_test.ok > expout
+cat $abs_srcdir/gmm/gmm_prim_network_test.err > experr
+AT_CHECK([$abs_top_builddir/tests/gmm/gmm_prim_network_test], [0], [expout], [experr])
+AT_CLEANUP
+
AT_SETUP([llc/llc])
AT_KEYWORDS([llc llc])
cat $abs_srcdir/llc/llc_test.ok > expout
To view, visit change 37726. To unsubscribe, or for help writing mail filters, visit settings.