llc/test: Add test program for LLC related tests

Sponsored-by: On-Waves ehf
diff --git a/tests/Makefile.am b/tests/Makefile.am
index a9fc9dd..5d7aab0 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -1,7 +1,7 @@
 AM_CPPFLAGS = $(STD_DEFINES_AND_INCLUDES) $(LIBOSMOCORE_CFLAGS) $(LIBOSMOGB_CFLAGS) $(LIBOSMOGSM_CFLAGS) -I$(top_srcdir)/src/
 AM_LDFLAGS = -lrt
 
-check_PROGRAMS = rlcmac/RLCMACTest alloc/AllocTest tbf/TbfTest types/TypesTest ms/MsTest llist/LListTest
+check_PROGRAMS = rlcmac/RLCMACTest alloc/AllocTest tbf/TbfTest types/TypesTest ms/MsTest llist/LListTest llc/LlcTest
 noinst_PROGRAMS = emu/pcu_emu
 
 rlcmac_RLCMACTest_SOURCES = rlcmac/RLCMACTest.cpp
@@ -55,6 +55,17 @@
 ms_MsTest_LDFLAGS = \
 	-Wl,-u,bssgp_prim_cb
 
+llc_LlcTest_SOURCES = llc/LlcTest.cpp
+llc_LlcTest_LDADD = \
+	$(top_builddir)/src/libgprs.la \
+	$(LIBOSMOGB_LIBS) \
+	$(LIBOSMOGSM_LIBS) \
+	$(LIBOSMOCORE_LIBS) \
+	$(COMMON_LA)
+
+llc_LlcTest_LDFLAGS = \
+	-Wl,-u,bssgp_prim_cb
+
 llist_LListTest_SOURCES = llist/LListTest.cpp
 llist_LListTest_LDADD = \
 	$(LIBOSMOCORE_LIBS) \
@@ -85,6 +96,7 @@
 	tbf/TbfTest.ok tbf/TbfTest.err \
 	types/TypesTest.ok types/TypesTest.err \
 	ms/MsTest.ok ms/MsTest.err \
+	llc/LlcTest.ok llc/LlcTest.err \
 	llist/LListTest.ok llist/LListTest.err
 
 DISTCLEANFILES = atconfig
diff --git a/tests/llc/LlcTest.cpp b/tests/llc/LlcTest.cpp
new file mode 100644
index 0000000..9e1d35d
--- /dev/null
+++ b/tests/llc/LlcTest.cpp
@@ -0,0 +1,173 @@
+/*
+ * LlcTest.cpp
+ *
+ * Copyright (C) 2015 by Sysmocom s.f.m.c. GmbH
+ *
+ * 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 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/>.
+ *
+ */
+
+extern "C" {
+	#include <osmocom/core/linuxlist.h>
+}
+
+#include "llc.h"
+#include "gprs_debug.h"
+
+extern "C" {
+#include "pcu_vty.h"
+
+#include <osmocom/core/application.h>
+#include <osmocom/core/msgb.h>
+#include <osmocom/core/talloc.h>
+#include <osmocom/core/utils.h>
+#include <osmocom/vty/vty.h>
+}
+
+
+void *tall_pcu_ctx;
+int16_t spoof_mnc = 0, spoof_mcc = 0;
+
+static void enqueue_data(gprs_llc_queue *queue, const uint8_t *data, size_t len)
+{
+	struct timeval *tv;
+	uint8_t *msg_data;
+	struct msgb *llc_msg = msgb_alloc(len + sizeof(*tv) * 2,
+		"llc_pdu_queue");
+
+	tv = (struct timeval *)msgb_put(llc_msg, sizeof(*tv));
+	memset(tv, 0, sizeof(*tv));
+	tv = (struct timeval *)msgb_put(llc_msg, sizeof(*tv));
+	memset(tv, 0, sizeof(*tv));
+	msg_data = (uint8_t *)msgb_put(llc_msg, len);
+
+	memcpy(msg_data, data, len);
+
+	queue->enqueue(llc_msg);
+}
+
+static void dequeue_and_check(gprs_llc_queue *queue, const uint8_t *exp_data, size_t len)
+{
+	struct msgb *llc_msg;
+	uint8_t *msg_data;
+
+	llc_msg = queue->dequeue();
+	OSMO_ASSERT(llc_msg != NULL);
+
+	fprintf(stderr, "dequeued msg, length %d, data %s\n",
+		msgb_length(llc_msg), msgb_hexdump(llc_msg));
+
+	OSMO_ASSERT(msgb_length(llc_msg) >= 2*sizeof(struct timeval));
+	msgb_pull(llc_msg, sizeof(struct timeval));
+	msgb_pull(llc_msg, sizeof(struct timeval));
+
+	fprintf(stderr, "LLC message, length %d (expected %d)\n",
+		msgb_length(llc_msg), len);
+
+	OSMO_ASSERT(msgb_length(llc_msg) == len);
+	msg_data = msgb_data(llc_msg);
+
+	OSMO_ASSERT(memcmp(msg_data, exp_data, len) == 0);
+	msgb_free(llc_msg);
+}
+
+static void enqueue_data(gprs_llc_queue *queue, const char *message)
+{
+	enqueue_data(queue, (uint8_t *)(message), strlen(message));
+}
+
+static void dequeue_and_check(gprs_llc_queue *queue, const char *exp_message)
+{
+	dequeue_and_check(queue, (uint8_t *)(exp_message), strlen(exp_message));
+}
+
+static void test_llc_queue()
+{
+	gprs_llc_queue queue;
+
+	printf("=== start %s ===\n", __func__);
+
+	queue.init();
+	OSMO_ASSERT(queue.size() == 0);
+
+	enqueue_data(&queue, "LLC message");
+	OSMO_ASSERT(queue.size() == 1);
+
+	enqueue_data(&queue, "other LLC message");
+	OSMO_ASSERT(queue.size() == 2);
+
+	dequeue_and_check(&queue, "LLC message");
+	OSMO_ASSERT(queue.size() == 1);
+
+	dequeue_and_check(&queue, "other LLC message");
+	OSMO_ASSERT(queue.size() == 0);
+
+	enqueue_data(&queue, "LLC");
+	OSMO_ASSERT(queue.size() == 1);
+
+	queue.clear(NULL);
+	OSMO_ASSERT(queue.size() == 0);
+
+	printf("=== end %s ===\n", __func__);
+}
+
+static const struct log_info_cat default_categories[] = {
+	{"DPCU", "", "GPRS Packet Control Unit (PCU)", LOGL_INFO, 1},
+};
+
+static int filter_fn(const struct log_context *ctx,
+	struct log_target *tar)
+{
+	return 1;
+}
+
+const struct log_info debug_log_info = {
+	filter_fn,
+	(struct log_info_cat*)default_categories,
+	ARRAY_SIZE(default_categories),
+};
+
+int main(int argc, char **argv)
+{
+	struct vty_app_info pcu_vty_info = {0};
+
+	tall_pcu_ctx = talloc_named_const(NULL, 1, "LlcTest context");
+	if (!tall_pcu_ctx)
+		abort();
+
+	msgb_set_talloc_ctx(tall_pcu_ctx);
+	osmo_init_logging(&debug_log_info);
+	log_set_use_color(osmo_stderr_target, 0);
+	log_set_print_filename(osmo_stderr_target, 0);
+	log_set_log_level(osmo_stderr_target, LOGL_INFO);
+
+	vty_init(&pcu_vty_info);
+	pcu_vty_init(&debug_log_info);
+
+	test_llc_queue();
+
+	if (getenv("TALLOC_REPORT_FULL"))
+		talloc_report_full(tall_pcu_ctx, stderr);
+
+	return EXIT_SUCCESS;
+}
+
+extern "C" {
+void l1if_pdch_req() { abort(); }
+void l1if_connect_pdch() { abort(); }
+void l1if_close_pdch() { abort(); }
+void l1if_open_pdch() { abort(); }
+}
diff --git a/tests/llc/LlcTest.err b/tests/llc/LlcTest.err
new file mode 100644
index 0000000..5ebb368
--- /dev/null
+++ b/tests/llc/LlcTest.err
@@ -0,0 +1,4 @@
+dequeued msg, length 27, data 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 4c 4c 43 20 6d 65 73 73 61 67 65 
+LLC message, length 11 (expected 11)
+dequeued msg, length 33, data 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 6f 74 68 65 72 20 4c 4c 43 20 6d 65 73 73 61 67 65 
+LLC message, length 17 (expected 17)
diff --git a/tests/llc/LlcTest.ok b/tests/llc/LlcTest.ok
new file mode 100644
index 0000000..79e23cd
--- /dev/null
+++ b/tests/llc/LlcTest.ok
@@ -0,0 +1,2 @@
+=== start test_llc_queue ===
+=== end test_llc_queue ===
diff --git a/tests/testsuite.at b/tests/testsuite.at
index 1cadcd2..d7a85e5 100644
--- a/tests/testsuite.at
+++ b/tests/testsuite.at
@@ -37,6 +37,13 @@
 AT_CHECK([$OSMO_QEMU $abs_top_builddir/tests/ms/MsTest], [0], [expout], [experr])
 AT_CLEANUP
 
+AT_SETUP([llc])
+AT_KEYWORDS([llc])
+cat $abs_srcdir/llc/LlcTest.ok > expout
+cat $abs_srcdir/llc/LlcTest.err > experr
+AT_CHECK([$OSMO_QEMU $abs_top_builddir/tests/llc/LlcTest], [0], [expout], [experr])
+AT_CLEANUP
+
 AT_SETUP([llist])
 AT_KEYWORDS([llist])
 cat $abs_srcdir/llist/LListTest.ok > expout