[Replicant] [libsamsung-ipc] [PATCH 6/7] Partitions: android: add tests for open_android_modem_partition

Denis 'GNUtoo' Carikli GNUtoo at cyberdimension.org
Thu Mar 4 12:42:26 UTC 2021


Libraries typically have a public API and some internal
implementation of that API. In libsamsung-ipc, the public
API is defined in the include/ directory from the top directory.

When compiling and installing libsamsung-ipc, that include/
directory is installed as well.

Anything that is not defined in include/ is not part of that
public API.

However here we need to precisely test functions that are not
part of that public API: The open_android_modem_partition
function being tested here is only used by the herolte device,
and that device doesn't have a battery that is easily replaceable,
so most Replicant contributors will not want to get that device.

As currently all the non static symbols of libsamsung-ipc are
exported and that open_android_modem_partition isn't static,
we can simply link to libsamsung-ipc for now and use its
internal headers to access the functions to test.

If at some point, libsamsung-ipc only exports the symbols defined
in include/ we would need to find other ways to run such tests,
for instance by using test frameworks that take care of that or by
compiling libsamsung-ipc source code into the test programs.

Some of the code of the libsamsung-ipc-test utility was adapted
from code from the nv_data-md5 utility (which is currently in
tools/).

Signed-off-by: Denis 'GNUtoo' Carikli <GNUtoo at cyberdimension.org>
---
 Makefile.am                              |   1 +
 configure.ac                             |   1 +
 samsung-ipc/tests/Makefile.am            |  29 +++++
 samsung-ipc/tests/libsamsung-ipc-test.py |  54 ++++++++
 samsung-ipc/tests/main.c                 | 157 +++++++++++++++++++++++
 samsung-ipc/tests/partitions/android.c   |  96 ++++++++++++++
 samsung-ipc/tests/partitions/android.h   |  25 ++++
 scripts/guix.scm                         |   6 +-
 8 files changed, 366 insertions(+), 3 deletions(-)
 create mode 100644 samsung-ipc/tests/Makefile.am
 create mode 100755 samsung-ipc/tests/libsamsung-ipc-test.py
 create mode 100644 samsung-ipc/tests/main.c
 create mode 100644 samsung-ipc/tests/partitions/android.c
 create mode 100644 samsung-ipc/tests/partitions/android.h

diff --git a/Makefile.am b/Makefile.am
index f036c81..45669d8 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -2,6 +2,7 @@ NULL =
 
 SUBDIRS = \
 	samsung-ipc \
+	samsung-ipc/tests \
 	include \
 	tools \
 	$(NULL)
diff --git a/configure.ac b/configure.ac
index 8be122c..d59ef0f 100644
--- a/configure.ac
+++ b/configure.ac
@@ -44,6 +44,7 @@ AC_CONFIG_FILES([
     samsung-ipc.pc
     include/Makefile
     samsung-ipc/Makefile
+    samsung-ipc/tests/Makefile
     tools/Makefile
 ])
 AC_OUTPUT
diff --git a/samsung-ipc/tests/Makefile.am b/samsung-ipc/tests/Makefile.am
new file mode 100644
index 0000000..d049c74
--- /dev/null
+++ b/samsung-ipc/tests/Makefile.am
@@ -0,0 +1,29 @@
+NULL =
+
+AM_CFLAGS = \
+        -I$(top_srcdir)/include \
+        -I$(top_srcdir)/samsung-ipc \
+        $(OPENSSL_CFLAGS) \
+        $(NULL)
+
+if WANT_DEBUG
+AM_CFLAGS += -ggdb -O0 -DDEBUG
+endif
+
+bin_PROGRAMS = libsamsung-ipc-test
+
+libsamsung_ipc_test_SOURCES = \
+	main.c \
+	partitions/android.c \
+	partitions/android.h \
+	$(NULL)
+
+libsamsung_ipc_test_LDADD = $(top_builddir)/samsung-ipc/libsamsung-ipc.la
+libsamsung_ipc_test_LDFLAGS =
+
+# TODO: Find a way to make test more modular and represent each run of
+# libsamsung-ipc-test in TEST while having it implemented in a single
+# python file
+PY_LOG_COMPILER = $(PYTHON)
+TEST_EXTENSIONS = .py
+TESTS = libsamsung-ipc-test.py
diff --git a/samsung-ipc/tests/libsamsung-ipc-test.py b/samsung-ipc/tests/libsamsung-ipc-test.py
new file mode 100755
index 0000000..328f4f0
--- /dev/null
+++ b/samsung-ipc/tests/libsamsung-ipc-test.py
@@ -0,0 +1,54 @@
+#!/usr/bin/env python
+#
+#  This file is part of libsamsung-ipc.
+#
+#  Copyright (C) 2020 Denis 'GNUtoo' Carikli <GNUtoo at cyberdimension.org>
+#
+#  libsamsung-ipc is free software: you can redistribute it and/or modify
+#  it under the terms of the GNU General Public License as published by
+#  the Free Software Foundation, either version 2 of the License, or
+#  (at your option) any later version.
+#
+#  libsamsung-ipc 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 General Public License
+#  along with libsamsung-ipc.  If not, see <http://www.gnu.org/licenses/>.
+
+import os
+import re
+import sys
+import sh
+
+class libsamsung_ipc_test(object):
+    def __init__(self):
+        srcdir = os.environ.get('srcdir', None)
+
+        # Enable also to test without automake
+        if not srcdir:
+            srcdir = os.path.dirname(sys.argv[0])
+
+        self.run = sh.Command(srcdir + os.sep + "libsamsung-ipc-test")
+
+    def run_all_tests(self):
+        output = str(self.run("list-tests")).split(os.linesep)
+        # Remove the last line break from the output
+        output.remove('')
+
+        # Also Remove the first line from the output: We have an output like
+        # that:
+        # Available tests:
+        #  [list of tests]
+        output.pop(0)
+
+        for test_name in output:
+            self.run("test", test_name.replace(' ', ''))
+
+def main():
+    tests = libsamsung_ipc_test()
+    tests.run_all_tests()
+
+if __name__ == '__main__':
+    main()
diff --git a/samsung-ipc/tests/main.c b/samsung-ipc/tests/main.c
new file mode 100644
index 0000000..ffb855d
--- /dev/null
+++ b/samsung-ipc/tests/main.c
@@ -0,0 +1,157 @@
+/*
+ * This file is part of libsamsung-ipc.
+ *
+ * Copyright (C) 2016 Paul Kocialkowsk <contact at paulk.fr>
+ * Copyright (C) 2021 Denis 'GNUtoo' Carikli <GNUtoo at cyberdimension.org>
+ *
+ * libsamsung-ipc is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * libsamsung-ipc 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 General Public License
+ * along with libsamsung-ipc.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sysexits.h>
+
+#include <samsung-ipc.h>
+
+/* libsamsung-ipc internal headers */
+#include <ipc.h>
+#include "partitions/android.h"
+
+struct test {
+	char *name;
+	int (*func)(struct ipc_client *client);
+};
+
+static struct test tests[] = {
+	{
+		"open_android_modem_partition",
+		test_open_android_modem_partition
+	},
+};
+
+static void usage(const char *progname)
+{
+	printf("Usage: %s list-tests\n", progname);
+	printf("Usage: %s test <test>\n", progname);
+}
+
+static void list_tests(void)
+{
+	unsigned int i;
+
+	printf("Available tests:\n");
+
+	for (i = 0; i < sizeof(tests) / sizeof(struct test); i++)
+		printf("  %s\n", tests[i].name);
+}
+
+static struct test *get_test(char *name)
+{
+	unsigned int i;
+
+	for (i = 0; i < sizeof(tests) / sizeof(struct test); i++) {
+		if (!strcmp(tests[i].name, name))
+			return &(tests[i]);
+	}
+
+	return NULL;
+}
+
+static void log_callback(__attribute__((unused)) void *data,
+			 __attribute__((unused)) const char *message)
+{
+	/* TODO: add better logging mechanism in libsamsung-ipc with
+	 * tags and log levels which would enable to filter the
+	 * messages from different provenance (this file, the code
+	 * under test, other parts of libsamsung-ipc, etc).
+	 */
+#ifdef DEBUG
+	char *buffer;
+	size_t length;
+	int i;
+
+	if (message == NULL)
+		return;
+
+	buffer = strdup(message);
+	length = strlen(message);
+
+	for (i = length; i > 0; i--) {
+		if (buffer[i] == '\n')
+			buffer[i] = '\0';
+		else if (buffer[i] != '\0')
+			break;
+	}
+
+	printf("[ipc] %s\n", buffer);
+
+	free(buffer);
+#endif
+}
+
+int main(int argc, char *argv[])
+{
+	struct ipc_client *client = NULL;
+	const char *progname = "libsamsung-ipc-test";
+	char *given_test_name;
+	struct test *test;
+	int rc = 0;
+
+	if (argc == 2 && !strcmp("list-tests", argv[1])) {
+		list_tests();
+		return 0;
+	} else if (argc == 3 && !strcmp("test", argv[1])) {
+		given_test_name = argv[2];
+	} else {
+		usage(progname);
+		return EX_USAGE;
+	}
+
+	test = get_test(given_test_name);
+	if (test == NULL) {
+		printf("Unknown test %s\n", given_test_name);
+		return EX_USAGE;
+	}
+
+	client = ipc_client_create(IPC_CLIENT_TYPE_DUMMY);
+	if (client == NULL) {
+		printf("[ !! ] Creating client failed\n");
+		goto error;
+	}
+
+	rc = ipc_client_log_callback_register(client, log_callback, NULL);
+	if (rc < 0) {
+		printf("[ !! ] Registering log callback failed: error %d\n",
+		       rc);
+		goto error;
+	}
+
+	rc = test->func(client);
+	if (rc == 0) {
+		printf("[ OK ] %s succedded\n", test->name);
+	} else {
+		printf("[ !! ] %s failed\n", test->name);
+		goto error;
+	}
+
+	return 0;
+
+error:
+	if (client != NULL)
+		ipc_client_destroy(client);
+
+	return EX_SOFTWARE;
+}
diff --git a/samsung-ipc/tests/partitions/android.c b/samsung-ipc/tests/partitions/android.c
new file mode 100644
index 0000000..708480a
--- /dev/null
+++ b/samsung-ipc/tests/partitions/android.c
@@ -0,0 +1,96 @@
+/*
+ * This file is part of libsamsung-ipc.
+ *
+ * Copyright (C) 2021 Denis 'GNUtoo' Carikli <GNUtoo at cyberdimension.org>
+ *
+ * libsamsung-ipc is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * libsamsung-ipc 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 General Public License
+ * along with libsamsung-ipc.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <errno.h>
+#include <fcntl.h>
+#include <libgen.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include <samsung-ipc.h>
+
+#include <partitions/android/android.h>
+#include "android.h"
+
+static char const * const dummy_modem_image_paths[] = {
+	/* We can't use mktemp here since everything is const
+	 * echo libsamsung-ipc | sha1sum | cut -c-20
+	 * gives 55f4731d2e11e85bd889
+	 */
+	"/tmp/libsamsung-ipc.55f4731d2e11e85bd889/modem.img",
+	NULL
+};
+
+
+int create_dummy_modem_image(__attribute__((unused)) struct ipc_client *client,
+			     __attribute__((unused)) const char * const path)
+{
+	/* TODO: replace it by C code but make sure that the replacement code
+	 * is as robust as the shell commands
+	 */
+	system("mkdir -p /tmp/libsamsung-ipc.55f4731d2e11e85bd889/");
+	system("touch /tmp/libsamsung-ipc.55f4731d2e11e85bd889/modem.img");
+
+	return 0;
+}
+
+int test_open_android_modem_partition(struct ipc_client *client)
+{
+	int i;
+	int rc;
+
+	for (i = 0; dummy_modem_image_paths[i] != NULL; i++) {
+		rc = create_dummy_modem_image(client,
+					      dummy_modem_image_paths[i]);
+		if (rc == -1) {
+			ipc_client_log(
+				client,
+				"%s: create_dummy_modem_image(client, %s)"
+				" failed\n",
+				__func__, dummy_modem_image_paths[i]);
+			return -1;
+		}
+	}
+
+	rc = open_android_modem_partition(client, dummy_modem_image_paths);
+	if (rc == -1) {
+		rc = errno;
+		ipc_client_log(client, "%s: open_android_modem_partition"
+			       " failed with errror %d: %s\n",
+			       __func__, rc, strerror(rc));
+		errno = rc;
+		return -1;
+	}
+
+	rc = close(rc);
+	if (rc == -1) {
+		rc = errno;
+		ipc_client_log(client,
+			       "%s: close() failed with errror %d: %s\n",
+			       __func__, rc, strerror(rc));
+		return -1;
+	}
+
+	return 0;
+}
diff --git a/samsung-ipc/tests/partitions/android.h b/samsung-ipc/tests/partitions/android.h
new file mode 100644
index 0000000..a386bb7
--- /dev/null
+++ b/samsung-ipc/tests/partitions/android.h
@@ -0,0 +1,25 @@
+/*
+ * This file is part of libsamsung-ipc.
+ *
+ * Copyright (C) 2021 Denis 'GNUtoo' Carikli <GNUtoo at cyberdimension.org>
+ *
+ * libsamsung-ipc is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * libsamsung-ipc 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 General Public License
+ * along with libsamsung-ipc.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __TESTS_PARTITIONS_ANDROID_H__
+#define __TESTS_PARTITIONS_ANDROID_H__
+
+int test_open_android_modem_partition(struct ipc_client *client);
+
+#endif /* __TESTS_PARTITIONS_ANDROID_H__ */
diff --git a/scripts/guix.scm b/scripts/guix.scm
index c6e033a..a917a82 100644
--- a/scripts/guix.scm
+++ b/scripts/guix.scm
@@ -113,7 +113,7 @@
        (modify-phases %standard-phases
          (add-before 'build 'patch-python
            (lambda _
-             (substitute* (find-files "tools" ".*\\.py$")
+             (substitute* (find-files "." ".*\\.py$")
                (("/usr/bin/env python") (which "python3")))
            #t)))))
     (synopsis "libsamsung-ipc is a free software implementation of the Samsung IPC modem protocol")
@@ -154,7 +154,7 @@ found in many Samsung smartphones and tablets.")
       (modify-phases %standard-phases
                      (add-before 'build 'patch-python
                                  (lambda _
-                                   (substitute* (find-files "tools" ".*\\.py$")
+                                   (substitute* (find-files "." ".*\\.py$")
                                                 (("/usr/bin/env python") (which "python3")))
                                    #t)))
       #:make-flags (list ,%common-strict-cflags)))))
@@ -177,7 +177,7 @@ found in many Samsung smartphones and tablets.")
        (modify-phases %standard-phases
          (add-before 'build 'patch-python
            (lambda _
-             (substitute* (find-files "tools" ".*\\.py$")
+             (substitute* (find-files "." ".*\\.py$")
                (("/usr/bin/env python") (which "python3")))
              #t)))
      #:make-flags (list ,%common-strict-cflags ,%clang-strict-cflags)))))
-- 
2.30.1



More information about the Replicant mailing list