DPDK patches and discussions
 help / color / mirror / Atom feed
* [PATCH 0/3] restore cfgfile library tests
@ 2024-07-30 22:51 Stephen Hemminger
  2024-07-30 22:51 ` [PATCH 1/3] buildtools: add helper to convert text file to header Stephen Hemminger
                   ` (7 more replies)
  0 siblings, 8 replies; 34+ messages in thread
From: Stephen Hemminger @ 2024-07-30 22:51 UTC (permalink / raw)
  To: dev; +Cc: Stephen Hemminger

The cfgfile tests did not get built since conversion to meson
and they used an awkward way to manage the test data.

This patchset converts the tests to use a helper to take
text file and make it into a C header. Then use the C header
to generate temporary files as needed.

Stephen Hemminger (3):
  buildtools: add helper to convert text file to header
  test: restore cfgfile tests
  test: remove unused resource API

 app/meson.build                    |   3 +-
 app/test/meson.build               |   8 +-
 app/test/resource.c                | 276 -----------------------------
 app/test/resource.h                | 106 -----------
 app/test/test_cfgfile.c            | 160 +++++++++++------
 app/test/test_cfgfiles/meson.build |  19 ++
 app/test/test_resource.c           | 104 -----------
 buildtools/gen-header.py           |  36 ++++
 buildtools/meson.build             |   2 +-
 9 files changed, 164 insertions(+), 550 deletions(-)
 delete mode 100644 app/test/resource.c
 delete mode 100644 app/test/resource.h
 create mode 100644 app/test/test_cfgfiles/meson.build
 delete mode 100644 app/test/test_resource.c
 create mode 100644 buildtools/gen-header.py

-- 
2.43.0


^ permalink raw reply	[flat|nested] 34+ messages in thread

* [PATCH 1/3] buildtools: add helper to convert text file to header
  2024-07-30 22:51 [PATCH 0/3] restore cfgfile library tests Stephen Hemminger
@ 2024-07-30 22:51 ` Stephen Hemminger
  2024-07-30 22:51 ` [PATCH 2/3] test: restore cfgfile tests Stephen Hemminger
                   ` (6 subsequent siblings)
  7 siblings, 0 replies; 34+ messages in thread
From: Stephen Hemminger @ 2024-07-30 22:51 UTC (permalink / raw)
  To: dev; +Cc: Stephen Hemminger

Simple script to read a file and make it into a initialized
C string in a header file.

Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
 buildtools/gen-header.py | 36 ++++++++++++++++++++++++++++++++++++
 buildtools/meson.build   |  2 +-
 2 files changed, 37 insertions(+), 1 deletion(-)
 create mode 100644 buildtools/gen-header.py

diff --git a/buildtools/gen-header.py b/buildtools/gen-header.py
new file mode 100644
index 0000000000..06e645863c
--- /dev/null
+++ b/buildtools/gen-header.py
@@ -0,0 +1,36 @@
+#! /usr/bin/env python3
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright (c) 2023 Stephen Hemminger <stephen@networkplumber.org>
+
+"""
+Script to read a text file and convert it into a header file.
+"""
+import sys
+import os
+
+
+def main():
+    '''program main function'''
+    print(f'/* File autogenerated by {sys.argv[0]} */')
+    for path in sys.argv[1:]:
+        name = os.path.basename(path)
+        print()
+        print(f'/* generated from {name} */')
+        with open(path, "r") as f:
+            array = name.replace(".", "_")
+            print(f'static const char {array}[] = ' + '{')
+            line = f.readline()
+
+            # make sure empty string is null terminated
+            if not line:
+                print('    ""')
+
+            while line:
+                s = repr(line)
+                print('    {}'.format(s.replace("'", '"')))
+                line = f.readline()
+            print('};')
+
+
+if __name__ == "__main__":
+    main()
diff --git a/buildtools/meson.build b/buildtools/meson.build
index 3adf34e1a8..bc818a71d5 100644
--- a/buildtools/meson.build
+++ b/buildtools/meson.build
@@ -24,6 +24,7 @@ get_numa_count_cmd = py3 + files('get-numa-count.py')
 get_test_suites_cmd = py3 + files('get-test-suites.py')
 has_hugepages_cmd = py3 + files('has-hugepages.py')
 cmdline_gen_cmd = py3 + files('dpdk-cmdline-gen.py')
+header_gen_cmd = py3 + files('gen-header.py')
 
 # install any build tools that end-users might want also
 install_data([
@@ -48,4 +49,3 @@ else
     pmdinfo += 'ar'
     pmdinfogen += 'elf'
 endif
-
-- 
2.43.0


^ permalink raw reply	[flat|nested] 34+ messages in thread

* [PATCH 2/3] test: restore cfgfile tests
  2024-07-30 22:51 [PATCH 0/3] restore cfgfile library tests Stephen Hemminger
  2024-07-30 22:51 ` [PATCH 1/3] buildtools: add helper to convert text file to header Stephen Hemminger
@ 2024-07-30 22:51 ` Stephen Hemminger
  2024-07-30 22:51 ` [PATCH 3/3] test: remove unused resource API Stephen Hemminger
                   ` (5 subsequent siblings)
  7 siblings, 0 replies; 34+ messages in thread
From: Stephen Hemminger @ 2024-07-30 22:51 UTC (permalink / raw)
  To: dev; +Cc: Stephen Hemminger, Cristian Dumitrescu

These tests were not built since the conversion to meson.
Instead of using embedded resource functions, put data in include
file and generate before the test.

Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
 app/meson.build                    |   3 +-
 app/test/meson.build               |   6 +-
 app/test/test_cfgfile.c            | 160 ++++++++++++++++++-----------
 app/test/test_cfgfiles/meson.build |  19 ++++
 4 files changed, 127 insertions(+), 61 deletions(-)
 create mode 100644 app/test/test_cfgfiles/meson.build

diff --git a/app/meson.build b/app/meson.build
index 5b2c80c7a1..e2db888ae1 100644
--- a/app/meson.build
+++ b/app/meson.build
@@ -55,6 +55,7 @@ foreach app:apps
     build = true
     reason = '<unknown reason>' # set if build == false to explain
     sources = []
+    resources = []
     includes = []
     cflags = default_cflags
     ldflags = default_ldflags
@@ -115,7 +116,7 @@ foreach app:apps
     endif
 
     exec = executable('dpdk-' + name,
-            sources,
+            [ sources, resources ],
             c_args: cflags,
             link_args: ldflags,
             link_whole: link_libs,
diff --git a/app/test/meson.build b/app/test/meson.build
index e29258e6ec..c99d768ead 100644
--- a/app/test/meson.build
+++ b/app/test/meson.build
@@ -36,7 +36,7 @@ source_file_deps = {
     'test_bitratestats.c': ['metrics', 'bitratestats', 'ethdev'] + sample_packet_forward_deps,
     'test_bpf.c': ['bpf', 'net'],
     'test_byteorder.c': [],
-#    'test_cfgfile.c': ['cfgfile'],
+    'test_cfgfile.c': ['cfgfile'],
     'test_cksum.c': ['net'],
     'test_cksum_perf.c': ['net'],
     'test_cmdline.c': [],
@@ -263,3 +263,7 @@ if not is_windows
             build_by_default: true,
             install: false)
 endif
+
+subdir('test_cfgfiles')
+
+resources += test_cfgfile_h
diff --git a/app/test/test_cfgfile.c b/app/test/test_cfgfile.c
index a5e3d8699c..f34838dd85 100644
--- a/app/test/test_cfgfile.c
+++ b/app/test/test_cfgfile.c
@@ -5,47 +5,31 @@
 #include <stdio.h>
 #include <string.h>
 #include <stdint.h>
-#include <sys/queue.h>
+#include <unistd.h>
 
 #include <rte_cfgfile.h>
 
 #include "test.h"
-#include "resource.h"
 
-
-#define CFG_FILES_ETC "test_cfgfiles/etc"
-
-REGISTER_LINKED_RESOURCE(test_cfgfiles);
+#include "test_cfgfiles.h"
 
 static int
-test_cfgfile_setup(void)
+test_cfgfile_init(char *filename, const char *data)
 {
-	const struct resource *r;
-	int ret;
+	size_t len = strlen(data);
+	int fd;
 
-	r = resource_find("test_cfgfiles");
-	TEST_ASSERT_NOT_NULL(r, "missing resource test_cfgfiles");
+	fd = mkstemps(filename, strlen(".ini"));
+	if (fd < 0)
+		return fd;
 
-	ret = resource_untar(r);
-	TEST_ASSERT_SUCCESS(ret, "failed to untar %s", r->name);
-
-	return 0;
+	if (write(fd, data, len) != (int)len) {
+		close(fd);
+		return -1;
+	}
+	return fd;
 }
 
-static int
-test_cfgfile_cleanup(void)
-{
-	const struct resource *r;
-	int ret;
-
-	r = resource_find("test_cfgfiles");
-	TEST_ASSERT_NOT_NULL(r, "missing resource test_cfgfiles");
-
-	ret = resource_rm_by_tar(r);
-	TEST_ASSERT_SUCCESS(ret, "Failed to delete resource %s", r->name);
-
-	return 0;
-}
 
 static int
 _test_cfgfile_sample(struct rte_cfgfile *cfgfile)
@@ -87,9 +71,14 @@ static int
 test_cfgfile_sample1(void)
 {
 	struct rte_cfgfile *cfgfile;
-	int ret;
+	char filename[] = "/tmp/cfg_sample1_XXXXXX.ini";
+	int fd, ret;
 
-	cfgfile = rte_cfgfile_load(CFG_FILES_ETC "/sample1.ini", 0);
+	fd = test_cfgfile_init(filename, sample1_ini);
+	TEST_ASSERT(fd >= 0, "Failed to setup temp file");
+
+	cfgfile = rte_cfgfile_load(filename, 0);
+	close(fd);
 	TEST_ASSERT_NOT_NULL(cfgfile, "Failed to load config file");
 
 	ret = _test_cfgfile_sample(cfgfile);
@@ -98,6 +87,8 @@ test_cfgfile_sample1(void)
 	ret = rte_cfgfile_close(cfgfile);
 	TEST_ASSERT_SUCCESS(ret, "Failed to close cfgfile");
 
+	unlink(filename);
+
 	return 0;
 }
 
@@ -106,14 +97,18 @@ test_cfgfile_sample2(void)
 {
 	struct rte_cfgfile_parameters params;
 	struct rte_cfgfile *cfgfile;
-	int ret;
+	char filename[] = "/tmp/cfgile_sample2_XXXXXX.ini";
+	int fd, ret;
+
+	fd = test_cfgfile_init(filename, sample2_ini);
+	TEST_ASSERT(fd >= 0, "Failed to setup temp file");
 
 	/* override comment character */
 	memset(&params, 0, sizeof(params));
 	params.comment_character = '#';
 
-	cfgfile = rte_cfgfile_load_with_params(CFG_FILES_ETC "/sample2.ini", 0,
-					       &params);
+	cfgfile = rte_cfgfile_load_with_params(filename, 0, &params);
+	close(fd);
 	TEST_ASSERT_NOT_NULL(cfgfile, "Failed to parse sample2.ini");
 
 	ret = _test_cfgfile_sample(cfgfile);
@@ -122,6 +117,8 @@ test_cfgfile_sample2(void)
 	ret = rte_cfgfile_close(cfgfile);
 	TEST_ASSERT_SUCCESS(ret, "Failed to close cfgfile");
 
+	unlink(filename);
+
 	return 0;
 }
 
@@ -129,10 +126,15 @@ static int
 test_cfgfile_realloc_sections(void)
 {
 	struct rte_cfgfile *cfgfile;
-	int ret;
+	char filename[] = "/tmp/cfg_realloc_XXXXXX.ini";
+	int fd, ret;
 	const char *value;
 
-	cfgfile = rte_cfgfile_load(CFG_FILES_ETC "/realloc_sections.ini", 0);
+	fd = test_cfgfile_init(filename, realloc_sections_ini);
+	TEST_ASSERT(fd >= 0, "Failed to setup temp file");
+
+	cfgfile = rte_cfgfile_load(filename, 0);
+	close(fd);
 	TEST_ASSERT_NOT_NULL(cfgfile, "Failed to load config file");
 
 	ret = rte_cfgfile_num_sections(cfgfile, NULL, 0);
@@ -152,13 +154,15 @@ test_cfgfile_realloc_sections(void)
 	TEST_ASSERT(strcmp("value8_section9", value) == 0,
 		    "key unexpected value: %s", value);
 
-	ret = rte_cfgfile_save(cfgfile, "/tmp/cfgfile_save.ini");
+	ret = rte_cfgfile_save(cfgfile, "/tmp/cfg_save.ini");
 	TEST_ASSERT_SUCCESS(ret, "Failed to save *.ini file");
-	remove("/tmp/cfgfile_save.ini");
+	remove("/tmp/cfg_save.ini");
 
 	ret = rte_cfgfile_close(cfgfile);
 	TEST_ASSERT_SUCCESS(ret, "Failed to close cfgfile");
 
+	unlink(filename);
+
 	return 0;
 }
 
@@ -166,10 +170,17 @@ static int
 test_cfgfile_invalid_section_header(void)
 {
 	struct rte_cfgfile *cfgfile;
+	char filename[] = "/tmp/cfg_invalid_section_XXXXXX.ini";
+	int fd;
 
-	cfgfile = rte_cfgfile_load(CFG_FILES_ETC "/invalid_section.ini", 0);
+	fd = test_cfgfile_init(filename, invalid_section_ini);
+	TEST_ASSERT(fd >= 0, "Failed to setup temp file");
+
+	cfgfile = rte_cfgfile_load(filename, 0);
 	TEST_ASSERT_NULL(cfgfile, "Expected failure did not occur");
 
+	close(fd);
+	unlink(filename);
 	return 0;
 }
 
@@ -178,15 +189,21 @@ test_cfgfile_invalid_comment(void)
 {
 	struct rte_cfgfile_parameters params;
 	struct rte_cfgfile *cfgfile;
+	char filename[] = "/tmp/cfg_sample2_XXXXXX.ini";
+	int fd;
 
 	/* override comment character with an invalid one */
 	memset(&params, 0, sizeof(params));
 	params.comment_character = '$';
 
-	cfgfile = rte_cfgfile_load_with_params(CFG_FILES_ETC "/sample2.ini", 0,
-					       &params);
+	fd = test_cfgfile_init(filename, sample2_ini);
+	TEST_ASSERT(fd >= 0, "Failed to setup temp file");
+
+	cfgfile = rte_cfgfile_load_with_params(filename, 0, &params);
 	TEST_ASSERT_NULL(cfgfile, "Expected failure did not occur");
 
+	close(fd);
+	unlink(filename);
 	return 0;
 }
 
@@ -194,10 +211,17 @@ static int
 test_cfgfile_invalid_key_value_pair(void)
 {
 	struct rte_cfgfile *cfgfile;
+	char filename[] = "/tmp/cfg_empty_key_XXXXXX.ini";
+	int fd;
 
-	cfgfile = rte_cfgfile_load(CFG_FILES_ETC "/empty_key_value.ini", 0);
+	fd = test_cfgfile_init(filename, empty_key_value_ini);
+	TEST_ASSERT(fd >= 0, "Failed to setup temp file");
+
+	cfgfile = rte_cfgfile_load(filename, 0);
+	close(fd);
 	TEST_ASSERT_NULL(cfgfile, "Expected failure did not occur");
 
+	unlink(filename);
 	return 0;
 }
 
@@ -206,10 +230,15 @@ test_cfgfile_empty_key_value_pair(void)
 {
 	struct rte_cfgfile *cfgfile;
 	const char *value;
-	int ret;
+	char filename[] = "/tmp/cfg_empty_key_XXXXXX.ini";
+	int fd, ret;
+
+	fd = test_cfgfile_init(filename, empty_key_value_ini);
+	TEST_ASSERT(fd >= 0, "Failed to setup temp file");
+
+	cfgfile = rte_cfgfile_load(filename, CFG_FLAG_EMPTY_VALUES);
+	close(fd);
 
-	cfgfile = rte_cfgfile_load(CFG_FILES_ETC "/empty_key_value.ini",
-				   CFG_FLAG_EMPTY_VALUES);
 	TEST_ASSERT_NOT_NULL(cfgfile, "Failed to parse empty_key_value.ini");
 
 	ret = rte_cfgfile_num_sections(cfgfile, NULL, 0);
@@ -227,6 +256,7 @@ test_cfgfile_empty_key_value_pair(void)
 	ret = rte_cfgfile_close(cfgfile);
 	TEST_ASSERT_SUCCESS(ret, "Failed to close cfgfile");
 
+	unlink(filename);
 	return 0;
 }
 
@@ -234,10 +264,17 @@ static int
 test_cfgfile_missing_section(void)
 {
 	struct rte_cfgfile *cfgfile;
+	char filename[] = "/tmp/cfg_missing_section_XXXXXX.ini";
+	int fd;
 
-	cfgfile = rte_cfgfile_load(CFG_FILES_ETC "/missing_section.ini", 0);
-	TEST_ASSERT_NULL(cfgfile, "Expected failure did not occur");
+	fd = test_cfgfile_init(filename, missing_section_ini);
+	TEST_ASSERT(fd >= 0, "Failed to setup temp file");
 
+	cfgfile = rte_cfgfile_load(filename, 0);
+	close(fd);
+
+	TEST_ASSERT_NULL(cfgfile, "Expected failure did not occur");
+	unlink(filename);
 	return 0;
 }
 
@@ -246,10 +283,14 @@ test_cfgfile_global_properties(void)
 {
 	struct rte_cfgfile *cfgfile;
 	const char *value;
-	int ret;
+	char filename[] = "/tmp/cfg_missing_section_XXXXXX.ini";
+	int fd, ret;
 
-	cfgfile = rte_cfgfile_load(CFG_FILES_ETC "/missing_section.ini",
-				   CFG_FLAG_GLOBAL_SECTION);
+	fd = test_cfgfile_init(filename, missing_section_ini);
+	TEST_ASSERT(fd >= 0, "Failed to setup temp file");
+
+	cfgfile = rte_cfgfile_load(filename, CFG_FLAG_GLOBAL_SECTION);
+	close(fd);
 	TEST_ASSERT_NOT_NULL(cfgfile, "Failed to load config file");
 
 	ret = rte_cfgfile_num_sections(cfgfile, NULL, 0);
@@ -268,6 +309,7 @@ test_cfgfile_global_properties(void)
 	ret = rte_cfgfile_close(cfgfile);
 	TEST_ASSERT_SUCCESS(ret, "Failed to close cfgfile");
 
+	unlink(filename);
 	return 0;
 }
 
@@ -275,9 +317,14 @@ static int
 test_cfgfile_empty_file(void)
 {
 	struct rte_cfgfile *cfgfile;
-	int ret;
+	char filename[] = "/tmp/cfg_empty_XXXXXX.ini";
+	int fd, ret;
 
-	cfgfile = rte_cfgfile_load(CFG_FILES_ETC "/empty.ini", 0);
+	fd = test_cfgfile_init(filename, empty_ini);
+	TEST_ASSERT(fd >= 0, "Failed to setup temp file");
+
+	cfgfile = rte_cfgfile_load(filename, 0);
+	close(fd);
 	TEST_ASSERT_NOT_NULL(cfgfile, "Failed to load config file");
 
 	ret = rte_cfgfile_num_sections(cfgfile, NULL, 0);
@@ -286,15 +333,13 @@ test_cfgfile_empty_file(void)
 	ret = rte_cfgfile_close(cfgfile);
 	TEST_ASSERT_SUCCESS(ret, "Failed to close cfgfile");
 
+	unlink(filename);
 	return 0;
 }
 
 static int
 test_cfgfile(void)
 {
-	if (test_cfgfile_setup())
-		return -1;
-
 	if (test_cfgfile_sample1())
 		return -1;
 
@@ -325,10 +370,7 @@ test_cfgfile(void)
 	if (test_cfgfile_empty_file())
 		return -1;
 
-	if (test_cfgfile_cleanup())
-		return -1;
-
 	return 0;
 }
 
-REGISTER_TEST_COMMAND(cfgfile_autotest, test_cfgfile);
+REGISTER_FAST_TEST(cfgfile_autotest, true, true, test_cfgfile);
diff --git a/app/test/test_cfgfiles/meson.build b/app/test/test_cfgfiles/meson.build
new file mode 100644
index 0000000000..068b61044a
--- /dev/null
+++ b/app/test/test_cfgfiles/meson.build
@@ -0,0 +1,19 @@
+# SPDX-License-Identifier: BSD-3-Clause
+
+test_cfgfiles = files(
+    'etc/empty.ini',
+    'etc/empty_key_value.ini',
+    'etc/invalid_section.ini',
+    'etc/line_too_long.ini',
+    'etc/missing_section.ini',
+    'etc/realloc_sections.ini',
+    'etc/sample1.ini',
+    'etc/sample2.ini',
+)
+
+# generate the header file used in cfgfile test
+test_cfgfile_h = custom_target('test_cfgfile',
+                          output: 'test_cfgfiles.h',
+                          input: test_cfgfiles,
+                          capture: true,
+                          command: [ header_gen_cmd, '@INPUT@'])
-- 
2.43.0


^ permalink raw reply	[flat|nested] 34+ messages in thread

* [PATCH 3/3] test: remove unused resource API
  2024-07-30 22:51 [PATCH 0/3] restore cfgfile library tests Stephen Hemminger
  2024-07-30 22:51 ` [PATCH 1/3] buildtools: add helper to convert text file to header Stephen Hemminger
  2024-07-30 22:51 ` [PATCH 2/3] test: restore cfgfile tests Stephen Hemminger
@ 2024-07-30 22:51 ` Stephen Hemminger
  2024-07-31  4:20 ` [PATCH v2 0/3] restore cfgfile library tests Stephen Hemminger
                   ` (4 subsequent siblings)
  7 siblings, 0 replies; 34+ messages in thread
From: Stephen Hemminger @ 2024-07-30 22:51 UTC (permalink / raw)
  To: dev; +Cc: Stephen Hemminger

This API was used only for cfgfile tests and was never built
after the conversion to meson. Will be replaced by simpler
method of doing cfgfile tests.

Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
 app/test/meson.build     |   2 -
 app/test/resource.c      | 276 ---------------------------------------
 app/test/resource.h      | 106 ---------------
 app/test/test_resource.c | 104 ---------------
 4 files changed, 488 deletions(-)
 delete mode 100644 app/test/resource.c
 delete mode 100644 app/test/resource.h
 delete mode 100644 app/test/test_resource.c

diff --git a/app/test/meson.build b/app/test/meson.build
index c99d768ead..b2bb7c36f6 100644
--- a/app/test/meson.build
+++ b/app/test/meson.build
@@ -20,7 +20,6 @@ test_cryptodev_deps = ['bus_vdev', 'net', 'cryptodev', 'security']
 source_file_deps = {
     # The C files providing functionality to other test cases
     'packet_burst_generator.c': packet_burst_generator_deps,
-#    'resource.c': [],          # unused currently.
     'sample_packet_forward.c': sample_packet_forward_deps,
     'virtual_pmd.c': virtual_pmd_deps,
 
@@ -154,7 +153,6 @@ source_file_deps = {
     'test_reciprocal_division_perf.c': [],
     'test_red.c': ['sched'],
     'test_reorder.c': ['reorder'],
-#    'test_resource.c': [],
     'test_rib.c': ['net', 'rib'],
     'test_rib6.c': ['net', 'rib'],
     'test_ring.c': ['ptr_compress'],
diff --git a/app/test/resource.c b/app/test/resource.c
deleted file mode 100644
index 34465f1668..0000000000
--- a/app/test/resource.c
+++ /dev/null
@@ -1,276 +0,0 @@
-/* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2016 RehiveTech. All rights reserved.
- */
-
-#include <stdio.h>
-#include <string.h>
-#include <errno.h>
-#include <sys/queue.h>
-
-#include <rte_debug.h>
-
-#include "resource.h"
-
-struct resource_list resource_list = TAILQ_HEAD_INITIALIZER(resource_list);
-
-size_t resource_size(const struct resource *r)
-{
-	return r->end - r->begin;
-}
-
-const struct resource *resource_find(const char *name)
-{
-	struct resource *r;
-
-	TAILQ_FOREACH(r, &resource_list, next) {
-		RTE_VERIFY(r->name);
-
-		if (!strcmp(r->name, name))
-			return r;
-	}
-
-	return NULL;
-}
-
-int resource_fwrite(const struct resource *r, FILE *f)
-{
-	const size_t goal = resource_size(r);
-	size_t total = 0;
-
-	while (total < goal) {
-		size_t wlen = fwrite(r->begin + total, 1, goal - total, f);
-		if (wlen == 0) {
-			perror(__func__);
-			return -1;
-		}
-
-		total += wlen;
-	}
-
-	return 0;
-}
-
-int resource_fwrite_file(const struct resource *r, const char *fname)
-{
-	FILE *f;
-	int ret;
-
-	f = fopen(fname, "w");
-	if (f == NULL) {
-		perror(__func__);
-		return -1;
-	}
-
-	ret = resource_fwrite(r, f);
-	fclose(f);
-	return ret;
-}
-
-#ifdef RTE_APP_TEST_RESOURCE_TAR
-#include <archive.h>
-#include <archive_entry.h>
-
-static int do_copy(struct archive *r, struct archive *w)
-{
-	const void *buf;
-	size_t len;
-#if ARCHIVE_VERSION_NUMBER >= 3000000
-	int64_t off;
-#else
-	off_t off;
-#endif
-	int ret;
-
-	while (1) {
-		ret = archive_read_data_block(r, &buf, &len, &off);
-		if (ret == ARCHIVE_RETRY)
-			continue;
-
-		if (ret == ARCHIVE_EOF)
-			return 0;
-
-		if (ret != ARCHIVE_OK)
-			return ret;
-
-		do {
-			ret = archive_write_data_block(w, buf, len, off);
-			if (ret != ARCHIVE_OK && ret != ARCHIVE_RETRY)
-				return ret;
-		} while (ret != ARCHIVE_OK);
-	}
-}
-
-int resource_untar(const struct resource *res)
-{
-	struct archive *r;
-	struct archive *w;
-	struct archive_entry *e;
-	void *p;
-	int flags = 0;
-	int ret;
-
-	p = malloc(resource_size(res));
-	if (p == NULL)
-		rte_panic("Failed to malloc %zu B\n", resource_size(res));
-
-	memcpy(p, res->begin, resource_size(res));
-
-	r = archive_read_new();
-	if (r == NULL) {
-		free(p);
-		return -1;
-	}
-
-	archive_read_support_format_all(r);
-	archive_read_support_filter_all(r);
-
-	w = archive_write_disk_new();
-	if (w == NULL) {
-		archive_read_free(r);
-		free(p);
-		return -1;
-	}
-
-	flags |= ARCHIVE_EXTRACT_PERM;
-	flags |= ARCHIVE_EXTRACT_FFLAGS;
-	archive_write_disk_set_options(w, flags);
-	archive_write_disk_set_standard_lookup(w);
-
-	ret = archive_read_open_memory(r, p, resource_size(res));
-	if (ret != ARCHIVE_OK)
-		goto fail;
-
-	while (1) {
-		ret = archive_read_next_header(r, &e);
-		if (ret == ARCHIVE_EOF)
-			break;
-		if (ret != ARCHIVE_OK)
-			goto fail;
-
-		ret = archive_write_header(w, e);
-		if (ret == ARCHIVE_EOF)
-			break;
-		if (ret != ARCHIVE_OK)
-			goto fail;
-
-		if (archive_entry_size(e) == 0)
-			continue;
-
-		ret = do_copy(r, w);
-		if (ret != ARCHIVE_OK)
-			goto fail;
-
-		ret = archive_write_finish_entry(w);
-		if (ret != ARCHIVE_OK)
-			goto fail;
-	}
-
-	archive_write_free(w);
-	archive_read_free(r);
-	free(p);
-	return 0;
-
-fail:
-	archive_write_free(w);
-	archive_read_free(r);
-	free(p);
-	rte_panic("Failed: %s\n", archive_error_string(r));
-	return -1;
-}
-
-int resource_rm_by_tar(const struct resource *res)
-{
-	struct archive *r;
-	struct archive_entry *e;
-	void *p;
-	int try_again = 1;
-	int attempts = 0;
-	int ret;
-
-	p = malloc(resource_size(res));
-	if (p == NULL)
-		rte_panic("Failed to malloc %zu B\n", resource_size(res));
-
-	memcpy(p, res->begin, resource_size(res));
-
-	/*
-	 * If somebody creates a file somewhere inside the extracted TAR
-	 * hierarchy during a test the resource_rm_by_tar might loop
-	 * infinitely. We prevent this by adding the attempts counter there.
-	 * In normal case, max N iteration is done where N is the depth of
-	 * the file-hierarchy.
-	 */
-	while (try_again && attempts < 10000) {
-		r = archive_read_new();
-		if (r == NULL) {
-			free(p);
-			return -1;
-		}
-
-		archive_read_support_format_all(r);
-		archive_read_support_filter_all(r);
-
-		ret = archive_read_open_memory(r, p, resource_size(res));
-		if (ret != ARCHIVE_OK) {
-			fprintf(stderr, "Failed: %s\n",
-					archive_error_string(r));
-			goto fail;
-		}
-
-		try_again = 0;
-
-		while (1) {
-			ret = archive_read_next_header(r, &e);
-			if (ret == ARCHIVE_EOF)
-				break;
-			if (ret != ARCHIVE_OK)
-				goto fail;
-
-			ret = remove(archive_entry_pathname(e));
-			if (ret < 0) {
-				switch (errno) {
-				case ENOTEMPTY:
-				case EEXIST:
-					try_again = 1;
-					break;
-
-				/* should not usually happen: */
-				case ENOENT:
-				case ENOTDIR:
-				case EROFS:
-					attempts += 1;
-					continue;
-				default:
-					perror("Failed to remove file");
-					goto fail;
-				}
-			}
-		}
-
-		archive_read_free(r);
-		attempts += 1;
-	}
-
-	if (attempts >= 10000) {
-		fprintf(stderr, "Failed to remove archive\n");
-		free(p);
-		return -1;
-	}
-
-	free(p);
-	return 0;
-
-fail:
-	archive_read_free(r);
-	free(p);
-
-	rte_panic("Failed: %s\n", archive_error_string(r));
-	return -1;
-}
-
-#endif /* RTE_APP_TEST_RESOURCE_TAR */
-
-void resource_register(struct resource *r)
-{
-	TAILQ_INSERT_TAIL(&resource_list, r, next);
-}
diff --git a/app/test/resource.h b/app/test/resource.h
deleted file mode 100644
index c75ebd4b5d..0000000000
--- a/app/test/resource.h
+++ /dev/null
@@ -1,106 +0,0 @@
-/* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2016 RehiveTech. All rights reserved.
- */
-
-#ifndef _RESOURCE_H_
-#define _RESOURCE_H_
-
-/**
- * @file
- *
- * Test Resource API
- *
- * Each test can require and use some external resources. Usually, an external
- * resource is a file or a filesystem sub-hierarchy. A resource is included
- * inside the test executable.
- */
-
-#include <sys/queue.h>
-#include <stdio.h>
-#include <stddef.h>
-
-#include <rte_eal.h>
-#include <rte_common.h>
-
-TAILQ_HEAD(resource_list, resource);
-extern struct resource_list resource_list;
-
-/**
- * Representation of a resource. It points to the resource's binary data.
- * The semantics of the binary data are defined by the target test.
- */
-struct resource {
-	const char *name;  /**< Unique name of the resource */
-	const char *begin; /**< Start of resource data */
-	const char *end;   /**< End of resource data */
-	TAILQ_ENTRY(resource) next;
-};
-
-/**
- * @return size of the given resource
- */
-size_t resource_size(const struct resource *r);
-
-/**
- * Find a resource by name in the global list of resources.
- */
-const struct resource *resource_find(const char *name);
-
-/**
- * Write the raw data of the resource to the given file.
- * @return 0 on success
- */
-int resource_fwrite(const struct resource *r, FILE *f);
-
-/**
- * Write the raw data of the resource to the given file given by name.
- * The name is relative to the current working directory.
- * @return 0 on success
- */
-int resource_fwrite_file(const struct resource *r, const char *fname);
-
-/**
- * Treat the given resource as a tar archive. Extract
- * the archive to the current directory.
- */
-int resource_untar(const struct resource *res);
-
-/**
- * Treat the given resource as a tar archive. Remove
- * all files (related to the current directory) listed
- * in the tar archive.
- */
-int resource_rm_by_tar(const struct resource *res);
-
-/**
- * Register a resource in the global list of resources.
- * Not intended for direct use, please check the REGISTER_RESOURCE
- * macro.
- */
-void resource_register(struct resource *r);
-
-/**
- * Definition of a resource linked externally (by means of the used toolchain).
- * Only the base name of the resource is expected. The name refers to the
- * linked pointers beg_<name> and end_<name> provided externally.
- */
-#define REGISTER_LINKED_RESOURCE(n) \
-extern const char beg_ ##n;         \
-extern const char end_ ##n;         \
-REGISTER_RESOURCE(n, &beg_ ##n, &end_ ##n) \
-
-/**
- * Definition of a resource described by its name, and pointers begin, end.
- */
-#define REGISTER_RESOURCE(n, b, e) \
-static struct resource linkres_ ##n = {       \
-	.name = RTE_STR(n),     \
-	.begin = b,             \
-	.end = e,               \
-};                              \
-RTE_INIT(resinitfn_ ##n)	\
-{                               \
-	resource_register(&linkres_ ##n);  \
-}
-
-#endif
diff --git a/app/test/test_resource.c b/app/test/test_resource.c
deleted file mode 100644
index 05c27db203..0000000000
--- a/app/test/test_resource.c
+++ /dev/null
@@ -1,104 +0,0 @@
-/* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2016 RehiveTech. All rights reserved.
- */
-
-#include <stdio.h>
-#include <string.h>
-
-#include "test.h"
-#include "resource.h"
-
-const char test_resource_dpdk_blob[] = {
-	'\x44', '\x50', '\x44', '\x4b', '\x00'
-};
-
-REGISTER_RESOURCE(test_resource_dpdk,
-		test_resource_dpdk_blob, test_resource_dpdk_blob + 4);
-
-static int test_resource_dpdk(void)
-{
-	const struct resource *r;
-
-	r = resource_find("test_resource_dpdk");
-	TEST_ASSERT_NOT_NULL(r, "Could not find test_resource_dpdk");
-	TEST_ASSERT(!strcmp(r->name, "test_resource_dpdk"),
-			"Found resource %s, expected test_resource_dpdk",
-			r->name);
-
-	TEST_ASSERT(!strncmp("DPDK", r->begin, 4),
-			"Unexpected payload: %.4s...", r->begin);
-
-	return 0;
-}
-
-REGISTER_LINKED_RESOURCE(test_resource_c);
-
-static int test_resource_c(void)
-{
-	const struct resource *r;
-	FILE *f;
-
-	r = resource_find("test_resource_c");
-	TEST_ASSERT_NOT_NULL(r, "No test_resource_c found");
-	TEST_ASSERT(!strcmp(r->name, "test_resource_c"),
-			"Found resource %s, expected test_resource_c",
-			r->name);
-
-	TEST_ASSERT_SUCCESS(resource_fwrite_file(r, "test_resource.c"),
-			"Failed to write file %s", r->name);
-
-	f = fopen("test_resource.c", "r");
-	TEST_ASSERT_NOT_NULL(f,
-			"Missing extracted file resource.c");
-	fclose(f);
-	remove("test_resource.c");
-
-	return 0;
-}
-
-#ifdef RTE_APP_TEST_RESOURCE_TAR
-REGISTER_LINKED_RESOURCE(test_resource_tar);
-
-static int test_resource_tar(void)
-{
-	const struct resource *r;
-	FILE *f;
-
-	r = resource_find("test_resource_tar");
-	TEST_ASSERT_NOT_NULL(r, "No test_resource_tar found");
-	TEST_ASSERT(!strcmp(r->name, "test_resource_tar"),
-			"Found resource %s, expected test_resource_tar",
-			r->name);
-
-	TEST_ASSERT_SUCCESS(resource_untar(r),
-			"Failed to to untar %s", r->name);
-
-	f = fopen("test_resource.c", "r");
-	TEST_ASSERT_NOT_NULL(f,
-			"Missing extracted file test_resource.c");
-	fclose(f);
-
-	TEST_ASSERT_SUCCESS(resource_rm_by_tar(r),
-			"Failed to remove extracted contents of %s", r->name);
-	return 0;
-}
-
-#endif /* RTE_APP_TEST_RESOURCE_TAR */
-
-static int test_resource(void)
-{
-	if (test_resource_dpdk())
-		return -1;
-
-	if (test_resource_c())
-		return -1;
-
-#ifdef RTE_APP_TEST_RESOURCE_TAR
-	if (test_resource_tar())
-		return -1;
-#endif /* RTE_APP_TEST_RESOURCE_TAR */
-
-	return 0;
-}
-
-REGISTER_TEST_COMMAND(resource_autotest, test_resource);
-- 
2.43.0


^ permalink raw reply	[flat|nested] 34+ messages in thread

* [PATCH v2 0/3] restore cfgfile library tests
  2024-07-30 22:51 [PATCH 0/3] restore cfgfile library tests Stephen Hemminger
                   ` (2 preceding siblings ...)
  2024-07-30 22:51 ` [PATCH 3/3] test: remove unused resource API Stephen Hemminger
@ 2024-07-31  4:20 ` Stephen Hemminger
  2024-07-31  4:20   ` [PATCH v2 1/3] buildtools: add helper to convert text file to header Stephen Hemminger
                     ` (2 more replies)
  2024-07-31 17:35 ` [PATCH v3 0/3] restore lost tests for rte_cfgfile Stephen Hemminger
                   ` (3 subsequent siblings)
  7 siblings, 3 replies; 34+ messages in thread
From: Stephen Hemminger @ 2024-07-31  4:20 UTC (permalink / raw)
  To: dev; +Cc: Stephen Hemminger

The cfgfile tests did not get built since conversion to meson
and they used an awkward way to manage the test data.

This patchset converts the tests to use a helper to take
text file and make it into a C header. Then use the C header
to generate temporary files as needed.

v2 - use mkstemp instead of mktemps since the later does
     not exist on Windows (in mingw).

Stephen Hemminger (3):
  buildtools: add helper to convert text file to header
  test: restore cfgfile tests
  test: remove unused resource API

 app/meson.build                    |   3 +-
 app/test/meson.build               |   8 +-
 app/test/resource.c                | 276 -----------------------------
 app/test/resource.h                | 106 -----------
 app/test/test_cfgfile.c            | 164 ++++++++++-------
 app/test/test_cfgfiles/meson.build |  19 ++
 app/test/test_resource.c           | 104 -----------
 buildtools/gen-header.py           |  36 ++++
 buildtools/meson.build             |   2 +-
 9 files changed, 166 insertions(+), 552 deletions(-)
 delete mode 100644 app/test/resource.c
 delete mode 100644 app/test/resource.h
 create mode 100644 app/test/test_cfgfiles/meson.build
 delete mode 100644 app/test/test_resource.c
 create mode 100644 buildtools/gen-header.py

-- 
2.43.0


^ permalink raw reply	[flat|nested] 34+ messages in thread

* [PATCH v2 1/3] buildtools: add helper to convert text file to header
  2024-07-31  4:20 ` [PATCH v2 0/3] restore cfgfile library tests Stephen Hemminger
@ 2024-07-31  4:20   ` Stephen Hemminger
  2024-07-31  4:20   ` [PATCH v2 2/3] test: restore cfgfile tests Stephen Hemminger
  2024-07-31  4:20   ` [PATCH v2 3/3] test: remove unused resource API Stephen Hemminger
  2 siblings, 0 replies; 34+ messages in thread
From: Stephen Hemminger @ 2024-07-31  4:20 UTC (permalink / raw)
  To: dev; +Cc: Stephen Hemminger

Simple script to read a file and make it into a initialized
C string in a header file.

Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
 buildtools/gen-header.py | 36 ++++++++++++++++++++++++++++++++++++
 buildtools/meson.build   |  2 +-
 2 files changed, 37 insertions(+), 1 deletion(-)
 create mode 100644 buildtools/gen-header.py

diff --git a/buildtools/gen-header.py b/buildtools/gen-header.py
new file mode 100644
index 0000000000..06e645863c
--- /dev/null
+++ b/buildtools/gen-header.py
@@ -0,0 +1,36 @@
+#! /usr/bin/env python3
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright (c) 2023 Stephen Hemminger <stephen@networkplumber.org>
+
+"""
+Script to read a text file and convert it into a header file.
+"""
+import sys
+import os
+
+
+def main():
+    '''program main function'''
+    print(f'/* File autogenerated by {sys.argv[0]} */')
+    for path in sys.argv[1:]:
+        name = os.path.basename(path)
+        print()
+        print(f'/* generated from {name} */')
+        with open(path, "r") as f:
+            array = name.replace(".", "_")
+            print(f'static const char {array}[] = ' + '{')
+            line = f.readline()
+
+            # make sure empty string is null terminated
+            if not line:
+                print('    ""')
+
+            while line:
+                s = repr(line)
+                print('    {}'.format(s.replace("'", '"')))
+                line = f.readline()
+            print('};')
+
+
+if __name__ == "__main__":
+    main()
diff --git a/buildtools/meson.build b/buildtools/meson.build
index 3adf34e1a8..bc818a71d5 100644
--- a/buildtools/meson.build
+++ b/buildtools/meson.build
@@ -24,6 +24,7 @@ get_numa_count_cmd = py3 + files('get-numa-count.py')
 get_test_suites_cmd = py3 + files('get-test-suites.py')
 has_hugepages_cmd = py3 + files('has-hugepages.py')
 cmdline_gen_cmd = py3 + files('dpdk-cmdline-gen.py')
+header_gen_cmd = py3 + files('gen-header.py')
 
 # install any build tools that end-users might want also
 install_data([
@@ -48,4 +49,3 @@ else
     pmdinfo += 'ar'
     pmdinfogen += 'elf'
 endif
-
-- 
2.43.0


^ permalink raw reply	[flat|nested] 34+ messages in thread

* [PATCH v2 2/3] test: restore cfgfile tests
  2024-07-31  4:20 ` [PATCH v2 0/3] restore cfgfile library tests Stephen Hemminger
  2024-07-31  4:20   ` [PATCH v2 1/3] buildtools: add helper to convert text file to header Stephen Hemminger
@ 2024-07-31  4:20   ` Stephen Hemminger
  2024-07-31  4:20   ` [PATCH v2 3/3] test: remove unused resource API Stephen Hemminger
  2 siblings, 0 replies; 34+ messages in thread
From: Stephen Hemminger @ 2024-07-31  4:20 UTC (permalink / raw)
  To: dev; +Cc: Stephen Hemminger

These tests were not built since the conversion to meson.
Instead of using embedded resource functions, put data in include
file and generate before the test.

Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
 app/meson.build                    |   3 +-
 app/test/meson.build               |   6 +-
 app/test/test_cfgfile.c            | 160 ++++++++++++++++++-----------
 app/test/test_cfgfiles/meson.build |  19 ++++
 4 files changed, 127 insertions(+), 61 deletions(-)
 create mode 100644 app/test/test_cfgfiles/meson.build

diff --git a/app/meson.build b/app/meson.build
index 5b2c80c7a1..e2db888ae1 100644
--- a/app/meson.build
+++ b/app/meson.build
@@ -55,6 +55,7 @@ foreach app:apps
     build = true
     reason = '<unknown reason>' # set if build == false to explain
     sources = []
+    resources = []
     includes = []
     cflags = default_cflags
     ldflags = default_ldflags
@@ -115,7 +116,7 @@ foreach app:apps
     endif
 
     exec = executable('dpdk-' + name,
-            sources,
+            [ sources, resources ],
             c_args: cflags,
             link_args: ldflags,
             link_whole: link_libs,
diff --git a/app/test/meson.build b/app/test/meson.build
index e29258e6ec..c99d768ead 100644
--- a/app/test/meson.build
+++ b/app/test/meson.build
@@ -36,7 +36,7 @@ source_file_deps = {
     'test_bitratestats.c': ['metrics', 'bitratestats', 'ethdev'] + sample_packet_forward_deps,
     'test_bpf.c': ['bpf', 'net'],
     'test_byteorder.c': [],
-#    'test_cfgfile.c': ['cfgfile'],
+    'test_cfgfile.c': ['cfgfile'],
     'test_cksum.c': ['net'],
     'test_cksum_perf.c': ['net'],
     'test_cmdline.c': [],
@@ -263,3 +263,7 @@ if not is_windows
             build_by_default: true,
             install: false)
 endif
+
+subdir('test_cfgfiles')
+
+resources += test_cfgfile_h
diff --git a/app/test/test_cfgfile.c b/app/test/test_cfgfile.c
index a5e3d8699c..f34838dd85 100644
--- a/app/test/test_cfgfile.c
+++ b/app/test/test_cfgfile.c
@@ -5,47 +5,31 @@
 #include <stdio.h>
 #include <string.h>
 #include <stdint.h>
-#include <sys/queue.h>
+#include <unistd.h>
 
 #include <rte_cfgfile.h>
 
 #include "test.h"
-#include "resource.h"
 
-
-#define CFG_FILES_ETC "test_cfgfiles/etc"
-
-REGISTER_LINKED_RESOURCE(test_cfgfiles);
+#include "test_cfgfiles.h"
 
 static int
-test_cfgfile_setup(void)
+test_cfgfile_init(char *filename, const char *data)
 {
-	const struct resource *r;
-	int ret;
+	size_t len = strlen(data);
+	int fd;
 
-	r = resource_find("test_cfgfiles");
-	TEST_ASSERT_NOT_NULL(r, "missing resource test_cfgfiles");
+	fd = mkstemps(filename, strlen(".ini"));
+	if (fd < 0)
+		return fd;
 
-	ret = resource_untar(r);
-	TEST_ASSERT_SUCCESS(ret, "failed to untar %s", r->name);
-
-	return 0;
+	if (write(fd, data, len) != (int)len) {
+		close(fd);
+		return -1;
+	}
+	return fd;
 }
 
-static int
-test_cfgfile_cleanup(void)
-{
-	const struct resource *r;
-	int ret;
-
-	r = resource_find("test_cfgfiles");
-	TEST_ASSERT_NOT_NULL(r, "missing resource test_cfgfiles");
-
-	ret = resource_rm_by_tar(r);
-	TEST_ASSERT_SUCCESS(ret, "Failed to delete resource %s", r->name);
-
-	return 0;
-}
 
 static int
 _test_cfgfile_sample(struct rte_cfgfile *cfgfile)
@@ -87,9 +71,14 @@ static int
 test_cfgfile_sample1(void)
 {
 	struct rte_cfgfile *cfgfile;
-	int ret;
+	char filename[] = "/tmp/cfg_sample1_XXXXXX.ini";
+	int fd, ret;
 
-	cfgfile = rte_cfgfile_load(CFG_FILES_ETC "/sample1.ini", 0);
+	fd = test_cfgfile_init(filename, sample1_ini);
+	TEST_ASSERT(fd >= 0, "Failed to setup temp file");
+
+	cfgfile = rte_cfgfile_load(filename, 0);
+	close(fd);
 	TEST_ASSERT_NOT_NULL(cfgfile, "Failed to load config file");
 
 	ret = _test_cfgfile_sample(cfgfile);
@@ -98,6 +87,8 @@ test_cfgfile_sample1(void)
 	ret = rte_cfgfile_close(cfgfile);
 	TEST_ASSERT_SUCCESS(ret, "Failed to close cfgfile");
 
+	unlink(filename);
+
 	return 0;
 }
 
@@ -106,14 +97,18 @@ test_cfgfile_sample2(void)
 {
 	struct rte_cfgfile_parameters params;
 	struct rte_cfgfile *cfgfile;
-	int ret;
+	char filename[] = "/tmp/cfgile_sample2_XXXXXX.ini";
+	int fd, ret;
+
+	fd = test_cfgfile_init(filename, sample2_ini);
+	TEST_ASSERT(fd >= 0, "Failed to setup temp file");
 
 	/* override comment character */
 	memset(&params, 0, sizeof(params));
 	params.comment_character = '#';
 
-	cfgfile = rte_cfgfile_load_with_params(CFG_FILES_ETC "/sample2.ini", 0,
-					       &params);
+	cfgfile = rte_cfgfile_load_with_params(filename, 0, &params);
+	close(fd);
 	TEST_ASSERT_NOT_NULL(cfgfile, "Failed to parse sample2.ini");
 
 	ret = _test_cfgfile_sample(cfgfile);
@@ -122,6 +117,8 @@ test_cfgfile_sample2(void)
 	ret = rte_cfgfile_close(cfgfile);
 	TEST_ASSERT_SUCCESS(ret, "Failed to close cfgfile");
 
+	unlink(filename);
+
 	return 0;
 }
 
@@ -129,10 +126,15 @@ static int
 test_cfgfile_realloc_sections(void)
 {
 	struct rte_cfgfile *cfgfile;
-	int ret;
+	char filename[] = "/tmp/cfg_realloc_XXXXXX.ini";
+	int fd, ret;
 	const char *value;
 
-	cfgfile = rte_cfgfile_load(CFG_FILES_ETC "/realloc_sections.ini", 0);
+	fd = test_cfgfile_init(filename, realloc_sections_ini);
+	TEST_ASSERT(fd >= 0, "Failed to setup temp file");
+
+	cfgfile = rte_cfgfile_load(filename, 0);
+	close(fd);
 	TEST_ASSERT_NOT_NULL(cfgfile, "Failed to load config file");
 
 	ret = rte_cfgfile_num_sections(cfgfile, NULL, 0);
@@ -152,13 +154,15 @@ test_cfgfile_realloc_sections(void)
 	TEST_ASSERT(strcmp("value8_section9", value) == 0,
 		    "key unexpected value: %s", value);
 
-	ret = rte_cfgfile_save(cfgfile, "/tmp/cfgfile_save.ini");
+	ret = rte_cfgfile_save(cfgfile, "/tmp/cfg_save.ini");
 	TEST_ASSERT_SUCCESS(ret, "Failed to save *.ini file");
-	remove("/tmp/cfgfile_save.ini");
+	remove("/tmp/cfg_save.ini");
 
 	ret = rte_cfgfile_close(cfgfile);
 	TEST_ASSERT_SUCCESS(ret, "Failed to close cfgfile");
 
+	unlink(filename);
+
 	return 0;
 }
 
@@ -166,10 +170,17 @@ static int
 test_cfgfile_invalid_section_header(void)
 {
 	struct rte_cfgfile *cfgfile;
+	char filename[] = "/tmp/cfg_invalid_section_XXXXXX.ini";
+	int fd;
 
-	cfgfile = rte_cfgfile_load(CFG_FILES_ETC "/invalid_section.ini", 0);
+	fd = test_cfgfile_init(filename, invalid_section_ini);
+	TEST_ASSERT(fd >= 0, "Failed to setup temp file");
+
+	cfgfile = rte_cfgfile_load(filename, 0);
 	TEST_ASSERT_NULL(cfgfile, "Expected failure did not occur");
 
+	close(fd);
+	unlink(filename);
 	return 0;
 }
 
@@ -178,15 +189,21 @@ test_cfgfile_invalid_comment(void)
 {
 	struct rte_cfgfile_parameters params;
 	struct rte_cfgfile *cfgfile;
+	char filename[] = "/tmp/cfg_sample2_XXXXXX.ini";
+	int fd;
 
 	/* override comment character with an invalid one */
 	memset(&params, 0, sizeof(params));
 	params.comment_character = '$';
 
-	cfgfile = rte_cfgfile_load_with_params(CFG_FILES_ETC "/sample2.ini", 0,
-					       &params);
+	fd = test_cfgfile_init(filename, sample2_ini);
+	TEST_ASSERT(fd >= 0, "Failed to setup temp file");
+
+	cfgfile = rte_cfgfile_load_with_params(filename, 0, &params);
 	TEST_ASSERT_NULL(cfgfile, "Expected failure did not occur");
 
+	close(fd);
+	unlink(filename);
 	return 0;
 }
 
@@ -194,10 +211,17 @@ static int
 test_cfgfile_invalid_key_value_pair(void)
 {
 	struct rte_cfgfile *cfgfile;
+	char filename[] = "/tmp/cfg_empty_key_XXXXXX.ini";
+	int fd;
 
-	cfgfile = rte_cfgfile_load(CFG_FILES_ETC "/empty_key_value.ini", 0);
+	fd = test_cfgfile_init(filename, empty_key_value_ini);
+	TEST_ASSERT(fd >= 0, "Failed to setup temp file");
+
+	cfgfile = rte_cfgfile_load(filename, 0);
+	close(fd);
 	TEST_ASSERT_NULL(cfgfile, "Expected failure did not occur");
 
+	unlink(filename);
 	return 0;
 }
 
@@ -206,10 +230,15 @@ test_cfgfile_empty_key_value_pair(void)
 {
 	struct rte_cfgfile *cfgfile;
 	const char *value;
-	int ret;
+	char filename[] = "/tmp/cfg_empty_key_XXXXXX.ini";
+	int fd, ret;
+
+	fd = test_cfgfile_init(filename, empty_key_value_ini);
+	TEST_ASSERT(fd >= 0, "Failed to setup temp file");
+
+	cfgfile = rte_cfgfile_load(filename, CFG_FLAG_EMPTY_VALUES);
+	close(fd);
 
-	cfgfile = rte_cfgfile_load(CFG_FILES_ETC "/empty_key_value.ini",
-				   CFG_FLAG_EMPTY_VALUES);
 	TEST_ASSERT_NOT_NULL(cfgfile, "Failed to parse empty_key_value.ini");
 
 	ret = rte_cfgfile_num_sections(cfgfile, NULL, 0);
@@ -227,6 +256,7 @@ test_cfgfile_empty_key_value_pair(void)
 	ret = rte_cfgfile_close(cfgfile);
 	TEST_ASSERT_SUCCESS(ret, "Failed to close cfgfile");
 
+	unlink(filename);
 	return 0;
 }
 
@@ -234,10 +264,17 @@ static int
 test_cfgfile_missing_section(void)
 {
 	struct rte_cfgfile *cfgfile;
+	char filename[] = "/tmp/cfg_missing_section_XXXXXX.ini";
+	int fd;
 
-	cfgfile = rte_cfgfile_load(CFG_FILES_ETC "/missing_section.ini", 0);
-	TEST_ASSERT_NULL(cfgfile, "Expected failure did not occur");
+	fd = test_cfgfile_init(filename, missing_section_ini);
+	TEST_ASSERT(fd >= 0, "Failed to setup temp file");
 
+	cfgfile = rte_cfgfile_load(filename, 0);
+	close(fd);
+
+	TEST_ASSERT_NULL(cfgfile, "Expected failure did not occur");
+	unlink(filename);
 	return 0;
 }
 
@@ -246,10 +283,14 @@ test_cfgfile_global_properties(void)
 {
 	struct rte_cfgfile *cfgfile;
 	const char *value;
-	int ret;
+	char filename[] = "/tmp/cfg_missing_section_XXXXXX.ini";
+	int fd, ret;
 
-	cfgfile = rte_cfgfile_load(CFG_FILES_ETC "/missing_section.ini",
-				   CFG_FLAG_GLOBAL_SECTION);
+	fd = test_cfgfile_init(filename, missing_section_ini);
+	TEST_ASSERT(fd >= 0, "Failed to setup temp file");
+
+	cfgfile = rte_cfgfile_load(filename, CFG_FLAG_GLOBAL_SECTION);
+	close(fd);
 	TEST_ASSERT_NOT_NULL(cfgfile, "Failed to load config file");
 
 	ret = rte_cfgfile_num_sections(cfgfile, NULL, 0);
@@ -268,6 +309,7 @@ test_cfgfile_global_properties(void)
 	ret = rte_cfgfile_close(cfgfile);
 	TEST_ASSERT_SUCCESS(ret, "Failed to close cfgfile");
 
+	unlink(filename);
 	return 0;
 }
 
@@ -275,9 +317,14 @@ static int
 test_cfgfile_empty_file(void)
 {
 	struct rte_cfgfile *cfgfile;
-	int ret;
+	char filename[] = "/tmp/cfg_empty_XXXXXX.ini";
+	int fd, ret;
 
-	cfgfile = rte_cfgfile_load(CFG_FILES_ETC "/empty.ini", 0);
+	fd = test_cfgfile_init(filename, empty_ini);
+	TEST_ASSERT(fd >= 0, "Failed to setup temp file");
+
+	cfgfile = rte_cfgfile_load(filename, 0);
+	close(fd);
 	TEST_ASSERT_NOT_NULL(cfgfile, "Failed to load config file");
 
 	ret = rte_cfgfile_num_sections(cfgfile, NULL, 0);
@@ -286,15 +333,13 @@ test_cfgfile_empty_file(void)
 	ret = rte_cfgfile_close(cfgfile);
 	TEST_ASSERT_SUCCESS(ret, "Failed to close cfgfile");
 
+	unlink(filename);
 	return 0;
 }
 
 static int
 test_cfgfile(void)
 {
-	if (test_cfgfile_setup())
-		return -1;
-
 	if (test_cfgfile_sample1())
 		return -1;
 
@@ -325,10 +370,7 @@ test_cfgfile(void)
 	if (test_cfgfile_empty_file())
 		return -1;
 
-	if (test_cfgfile_cleanup())
-		return -1;
-
 	return 0;
 }
 
-REGISTER_TEST_COMMAND(cfgfile_autotest, test_cfgfile);
+REGISTER_FAST_TEST(cfgfile_autotest, true, true, test_cfgfile);
diff --git a/app/test/test_cfgfiles/meson.build b/app/test/test_cfgfiles/meson.build
new file mode 100644
index 0000000000..068b61044a
--- /dev/null
+++ b/app/test/test_cfgfiles/meson.build
@@ -0,0 +1,19 @@
+# SPDX-License-Identifier: BSD-3-Clause
+
+test_cfgfiles = files(
+    'etc/empty.ini',
+    'etc/empty_key_value.ini',
+    'etc/invalid_section.ini',
+    'etc/line_too_long.ini',
+    'etc/missing_section.ini',
+    'etc/realloc_sections.ini',
+    'etc/sample1.ini',
+    'etc/sample2.ini',
+)
+
+# generate the header file used in cfgfile test
+test_cfgfile_h = custom_target('test_cfgfile',
+                          output: 'test_cfgfiles.h',
+                          input: test_cfgfiles,
+                          capture: true,
+                          command: [ header_gen_cmd, '@INPUT@'])
-- 
2.43.0


^ permalink raw reply	[flat|nested] 34+ messages in thread

* [PATCH v2 3/3] test: remove unused resource API
  2024-07-31  4:20 ` [PATCH v2 0/3] restore cfgfile library tests Stephen Hemminger
  2024-07-31  4:20   ` [PATCH v2 1/3] buildtools: add helper to convert text file to header Stephen Hemminger
  2024-07-31  4:20   ` [PATCH v2 2/3] test: restore cfgfile tests Stephen Hemminger
@ 2024-07-31  4:20   ` Stephen Hemminger
  2 siblings, 0 replies; 34+ messages in thread
From: Stephen Hemminger @ 2024-07-31  4:20 UTC (permalink / raw)
  To: dev; +Cc: Stephen Hemminger

This API was used only for cfgfile tests and was never built
after the conversion to meson. Will be replaced by simpler
method of doing cfgfile tests.

Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
 app/test/meson.build     |   2 -
 app/test/resource.c      | 276 ---------------------------------------
 app/test/resource.h      | 106 ---------------
 app/test/test_cfgfile.c  |  46 +++----
 app/test/test_resource.c | 104 ---------------
 5 files changed, 23 insertions(+), 511 deletions(-)
 delete mode 100644 app/test/resource.c
 delete mode 100644 app/test/resource.h
 delete mode 100644 app/test/test_resource.c

diff --git a/app/test/meson.build b/app/test/meson.build
index c99d768ead..b2bb7c36f6 100644
--- a/app/test/meson.build
+++ b/app/test/meson.build
@@ -20,7 +20,6 @@ test_cryptodev_deps = ['bus_vdev', 'net', 'cryptodev', 'security']
 source_file_deps = {
     # The C files providing functionality to other test cases
     'packet_burst_generator.c': packet_burst_generator_deps,
-#    'resource.c': [],          # unused currently.
     'sample_packet_forward.c': sample_packet_forward_deps,
     'virtual_pmd.c': virtual_pmd_deps,
 
@@ -154,7 +153,6 @@ source_file_deps = {
     'test_reciprocal_division_perf.c': [],
     'test_red.c': ['sched'],
     'test_reorder.c': ['reorder'],
-#    'test_resource.c': [],
     'test_rib.c': ['net', 'rib'],
     'test_rib6.c': ['net', 'rib'],
     'test_ring.c': ['ptr_compress'],
diff --git a/app/test/resource.c b/app/test/resource.c
deleted file mode 100644
index 34465f1668..0000000000
--- a/app/test/resource.c
+++ /dev/null
@@ -1,276 +0,0 @@
-/* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2016 RehiveTech. All rights reserved.
- */
-
-#include <stdio.h>
-#include <string.h>
-#include <errno.h>
-#include <sys/queue.h>
-
-#include <rte_debug.h>
-
-#include "resource.h"
-
-struct resource_list resource_list = TAILQ_HEAD_INITIALIZER(resource_list);
-
-size_t resource_size(const struct resource *r)
-{
-	return r->end - r->begin;
-}
-
-const struct resource *resource_find(const char *name)
-{
-	struct resource *r;
-
-	TAILQ_FOREACH(r, &resource_list, next) {
-		RTE_VERIFY(r->name);
-
-		if (!strcmp(r->name, name))
-			return r;
-	}
-
-	return NULL;
-}
-
-int resource_fwrite(const struct resource *r, FILE *f)
-{
-	const size_t goal = resource_size(r);
-	size_t total = 0;
-
-	while (total < goal) {
-		size_t wlen = fwrite(r->begin + total, 1, goal - total, f);
-		if (wlen == 0) {
-			perror(__func__);
-			return -1;
-		}
-
-		total += wlen;
-	}
-
-	return 0;
-}
-
-int resource_fwrite_file(const struct resource *r, const char *fname)
-{
-	FILE *f;
-	int ret;
-
-	f = fopen(fname, "w");
-	if (f == NULL) {
-		perror(__func__);
-		return -1;
-	}
-
-	ret = resource_fwrite(r, f);
-	fclose(f);
-	return ret;
-}
-
-#ifdef RTE_APP_TEST_RESOURCE_TAR
-#include <archive.h>
-#include <archive_entry.h>
-
-static int do_copy(struct archive *r, struct archive *w)
-{
-	const void *buf;
-	size_t len;
-#if ARCHIVE_VERSION_NUMBER >= 3000000
-	int64_t off;
-#else
-	off_t off;
-#endif
-	int ret;
-
-	while (1) {
-		ret = archive_read_data_block(r, &buf, &len, &off);
-		if (ret == ARCHIVE_RETRY)
-			continue;
-
-		if (ret == ARCHIVE_EOF)
-			return 0;
-
-		if (ret != ARCHIVE_OK)
-			return ret;
-
-		do {
-			ret = archive_write_data_block(w, buf, len, off);
-			if (ret != ARCHIVE_OK && ret != ARCHIVE_RETRY)
-				return ret;
-		} while (ret != ARCHIVE_OK);
-	}
-}
-
-int resource_untar(const struct resource *res)
-{
-	struct archive *r;
-	struct archive *w;
-	struct archive_entry *e;
-	void *p;
-	int flags = 0;
-	int ret;
-
-	p = malloc(resource_size(res));
-	if (p == NULL)
-		rte_panic("Failed to malloc %zu B\n", resource_size(res));
-
-	memcpy(p, res->begin, resource_size(res));
-
-	r = archive_read_new();
-	if (r == NULL) {
-		free(p);
-		return -1;
-	}
-
-	archive_read_support_format_all(r);
-	archive_read_support_filter_all(r);
-
-	w = archive_write_disk_new();
-	if (w == NULL) {
-		archive_read_free(r);
-		free(p);
-		return -1;
-	}
-
-	flags |= ARCHIVE_EXTRACT_PERM;
-	flags |= ARCHIVE_EXTRACT_FFLAGS;
-	archive_write_disk_set_options(w, flags);
-	archive_write_disk_set_standard_lookup(w);
-
-	ret = archive_read_open_memory(r, p, resource_size(res));
-	if (ret != ARCHIVE_OK)
-		goto fail;
-
-	while (1) {
-		ret = archive_read_next_header(r, &e);
-		if (ret == ARCHIVE_EOF)
-			break;
-		if (ret != ARCHIVE_OK)
-			goto fail;
-
-		ret = archive_write_header(w, e);
-		if (ret == ARCHIVE_EOF)
-			break;
-		if (ret != ARCHIVE_OK)
-			goto fail;
-
-		if (archive_entry_size(e) == 0)
-			continue;
-
-		ret = do_copy(r, w);
-		if (ret != ARCHIVE_OK)
-			goto fail;
-
-		ret = archive_write_finish_entry(w);
-		if (ret != ARCHIVE_OK)
-			goto fail;
-	}
-
-	archive_write_free(w);
-	archive_read_free(r);
-	free(p);
-	return 0;
-
-fail:
-	archive_write_free(w);
-	archive_read_free(r);
-	free(p);
-	rte_panic("Failed: %s\n", archive_error_string(r));
-	return -1;
-}
-
-int resource_rm_by_tar(const struct resource *res)
-{
-	struct archive *r;
-	struct archive_entry *e;
-	void *p;
-	int try_again = 1;
-	int attempts = 0;
-	int ret;
-
-	p = malloc(resource_size(res));
-	if (p == NULL)
-		rte_panic("Failed to malloc %zu B\n", resource_size(res));
-
-	memcpy(p, res->begin, resource_size(res));
-
-	/*
-	 * If somebody creates a file somewhere inside the extracted TAR
-	 * hierarchy during a test the resource_rm_by_tar might loop
-	 * infinitely. We prevent this by adding the attempts counter there.
-	 * In normal case, max N iteration is done where N is the depth of
-	 * the file-hierarchy.
-	 */
-	while (try_again && attempts < 10000) {
-		r = archive_read_new();
-		if (r == NULL) {
-			free(p);
-			return -1;
-		}
-
-		archive_read_support_format_all(r);
-		archive_read_support_filter_all(r);
-
-		ret = archive_read_open_memory(r, p, resource_size(res));
-		if (ret != ARCHIVE_OK) {
-			fprintf(stderr, "Failed: %s\n",
-					archive_error_string(r));
-			goto fail;
-		}
-
-		try_again = 0;
-
-		while (1) {
-			ret = archive_read_next_header(r, &e);
-			if (ret == ARCHIVE_EOF)
-				break;
-			if (ret != ARCHIVE_OK)
-				goto fail;
-
-			ret = remove(archive_entry_pathname(e));
-			if (ret < 0) {
-				switch (errno) {
-				case ENOTEMPTY:
-				case EEXIST:
-					try_again = 1;
-					break;
-
-				/* should not usually happen: */
-				case ENOENT:
-				case ENOTDIR:
-				case EROFS:
-					attempts += 1;
-					continue;
-				default:
-					perror("Failed to remove file");
-					goto fail;
-				}
-			}
-		}
-
-		archive_read_free(r);
-		attempts += 1;
-	}
-
-	if (attempts >= 10000) {
-		fprintf(stderr, "Failed to remove archive\n");
-		free(p);
-		return -1;
-	}
-
-	free(p);
-	return 0;
-
-fail:
-	archive_read_free(r);
-	free(p);
-
-	rte_panic("Failed: %s\n", archive_error_string(r));
-	return -1;
-}
-
-#endif /* RTE_APP_TEST_RESOURCE_TAR */
-
-void resource_register(struct resource *r)
-{
-	TAILQ_INSERT_TAIL(&resource_list, r, next);
-}
diff --git a/app/test/resource.h b/app/test/resource.h
deleted file mode 100644
index c75ebd4b5d..0000000000
--- a/app/test/resource.h
+++ /dev/null
@@ -1,106 +0,0 @@
-/* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2016 RehiveTech. All rights reserved.
- */
-
-#ifndef _RESOURCE_H_
-#define _RESOURCE_H_
-
-/**
- * @file
- *
- * Test Resource API
- *
- * Each test can require and use some external resources. Usually, an external
- * resource is a file or a filesystem sub-hierarchy. A resource is included
- * inside the test executable.
- */
-
-#include <sys/queue.h>
-#include <stdio.h>
-#include <stddef.h>
-
-#include <rte_eal.h>
-#include <rte_common.h>
-
-TAILQ_HEAD(resource_list, resource);
-extern struct resource_list resource_list;
-
-/**
- * Representation of a resource. It points to the resource's binary data.
- * The semantics of the binary data are defined by the target test.
- */
-struct resource {
-	const char *name;  /**< Unique name of the resource */
-	const char *begin; /**< Start of resource data */
-	const char *end;   /**< End of resource data */
-	TAILQ_ENTRY(resource) next;
-};
-
-/**
- * @return size of the given resource
- */
-size_t resource_size(const struct resource *r);
-
-/**
- * Find a resource by name in the global list of resources.
- */
-const struct resource *resource_find(const char *name);
-
-/**
- * Write the raw data of the resource to the given file.
- * @return 0 on success
- */
-int resource_fwrite(const struct resource *r, FILE *f);
-
-/**
- * Write the raw data of the resource to the given file given by name.
- * The name is relative to the current working directory.
- * @return 0 on success
- */
-int resource_fwrite_file(const struct resource *r, const char *fname);
-
-/**
- * Treat the given resource as a tar archive. Extract
- * the archive to the current directory.
- */
-int resource_untar(const struct resource *res);
-
-/**
- * Treat the given resource as a tar archive. Remove
- * all files (related to the current directory) listed
- * in the tar archive.
- */
-int resource_rm_by_tar(const struct resource *res);
-
-/**
- * Register a resource in the global list of resources.
- * Not intended for direct use, please check the REGISTER_RESOURCE
- * macro.
- */
-void resource_register(struct resource *r);
-
-/**
- * Definition of a resource linked externally (by means of the used toolchain).
- * Only the base name of the resource is expected. The name refers to the
- * linked pointers beg_<name> and end_<name> provided externally.
- */
-#define REGISTER_LINKED_RESOURCE(n) \
-extern const char beg_ ##n;         \
-extern const char end_ ##n;         \
-REGISTER_RESOURCE(n, &beg_ ##n, &end_ ##n) \
-
-/**
- * Definition of a resource described by its name, and pointers begin, end.
- */
-#define REGISTER_RESOURCE(n, b, e) \
-static struct resource linkres_ ##n = {       \
-	.name = RTE_STR(n),     \
-	.begin = b,             \
-	.end = e,               \
-};                              \
-RTE_INIT(resinitfn_ ##n)	\
-{                               \
-	resource_register(&linkres_ ##n);  \
-}
-
-#endif
diff --git a/app/test/test_cfgfile.c b/app/test/test_cfgfile.c
index f34838dd85..8db9f721ce 100644
--- a/app/test/test_cfgfile.c
+++ b/app/test/test_cfgfile.c
@@ -19,7 +19,7 @@ test_cfgfile_init(char *filename, const char *data)
 	size_t len = strlen(data);
 	int fd;
 
-	fd = mkstemps(filename, strlen(".ini"));
+	fd = mkstemp(filename);
 	if (fd < 0)
 		return fd;
 
@@ -71,7 +71,7 @@ static int
 test_cfgfile_sample1(void)
 {
 	struct rte_cfgfile *cfgfile;
-	char filename[] = "/tmp/cfg_sample1_XXXXXX.ini";
+	char filename[] = "/tmp/cfg_sample1_XXXXXX";
 	int fd, ret;
 
 	fd = test_cfgfile_init(filename, sample1_ini);
@@ -87,7 +87,7 @@ test_cfgfile_sample1(void)
 	ret = rte_cfgfile_close(cfgfile);
 	TEST_ASSERT_SUCCESS(ret, "Failed to close cfgfile");
 
-	unlink(filename);
+	remove(filename);
 
 	return 0;
 }
@@ -97,7 +97,7 @@ test_cfgfile_sample2(void)
 {
 	struct rte_cfgfile_parameters params;
 	struct rte_cfgfile *cfgfile;
-	char filename[] = "/tmp/cfgile_sample2_XXXXXX.ini";
+	char filename[] = "/tmp/cfgile_sample2_XXXXXX";
 	int fd, ret;
 
 	fd = test_cfgfile_init(filename, sample2_ini);
@@ -109,7 +109,7 @@ test_cfgfile_sample2(void)
 
 	cfgfile = rte_cfgfile_load_with_params(filename, 0, &params);
 	close(fd);
-	TEST_ASSERT_NOT_NULL(cfgfile, "Failed to parse sample2.ini");
+	TEST_ASSERT_NOT_NULL(cfgfile, "Failed to parse sample2");
 
 	ret = _test_cfgfile_sample(cfgfile);
 	TEST_ASSERT_SUCCESS(ret, "Failed to validate sample file: %d", ret);
@@ -117,7 +117,7 @@ test_cfgfile_sample2(void)
 	ret = rte_cfgfile_close(cfgfile);
 	TEST_ASSERT_SUCCESS(ret, "Failed to close cfgfile");
 
-	unlink(filename);
+	remove(filename);
 
 	return 0;
 }
@@ -126,7 +126,7 @@ static int
 test_cfgfile_realloc_sections(void)
 {
 	struct rte_cfgfile *cfgfile;
-	char filename[] = "/tmp/cfg_realloc_XXXXXX.ini";
+	char filename[] = "/tmp/cfg_realloc_XXXXXX";
 	int fd, ret;
 	const char *value;
 
@@ -161,7 +161,7 @@ test_cfgfile_realloc_sections(void)
 	ret = rte_cfgfile_close(cfgfile);
 	TEST_ASSERT_SUCCESS(ret, "Failed to close cfgfile");
 
-	unlink(filename);
+	remove(filename);
 
 	return 0;
 }
@@ -170,7 +170,7 @@ static int
 test_cfgfile_invalid_section_header(void)
 {
 	struct rte_cfgfile *cfgfile;
-	char filename[] = "/tmp/cfg_invalid_section_XXXXXX.ini";
+	char filename[] = "/tmp/cfg_invalid_section_XXXXXX";
 	int fd;
 
 	fd = test_cfgfile_init(filename, invalid_section_ini);
@@ -180,7 +180,7 @@ test_cfgfile_invalid_section_header(void)
 	TEST_ASSERT_NULL(cfgfile, "Expected failure did not occur");
 
 	close(fd);
-	unlink(filename);
+	remove(filename);
 	return 0;
 }
 
@@ -189,7 +189,7 @@ test_cfgfile_invalid_comment(void)
 {
 	struct rte_cfgfile_parameters params;
 	struct rte_cfgfile *cfgfile;
-	char filename[] = "/tmp/cfg_sample2_XXXXXX.ini";
+	char filename[] = "/tmp/cfg_sample2_XXXXXX";
 	int fd;
 
 	/* override comment character with an invalid one */
@@ -203,7 +203,7 @@ test_cfgfile_invalid_comment(void)
 	TEST_ASSERT_NULL(cfgfile, "Expected failure did not occur");
 
 	close(fd);
-	unlink(filename);
+	remove(filename);
 	return 0;
 }
 
@@ -211,7 +211,7 @@ static int
 test_cfgfile_invalid_key_value_pair(void)
 {
 	struct rte_cfgfile *cfgfile;
-	char filename[] = "/tmp/cfg_empty_key_XXXXXX.ini";
+	char filename[] = "/tmp/cfg_empty_key_XXXXXX";
 	int fd;
 
 	fd = test_cfgfile_init(filename, empty_key_value_ini);
@@ -221,7 +221,7 @@ test_cfgfile_invalid_key_value_pair(void)
 	close(fd);
 	TEST_ASSERT_NULL(cfgfile, "Expected failure did not occur");
 
-	unlink(filename);
+	remove(filename);
 	return 0;
 }
 
@@ -230,7 +230,7 @@ test_cfgfile_empty_key_value_pair(void)
 {
 	struct rte_cfgfile *cfgfile;
 	const char *value;
-	char filename[] = "/tmp/cfg_empty_key_XXXXXX.ini";
+	char filename[] = "/tmp/cfg_empty_key_XXXXXX";
 	int fd, ret;
 
 	fd = test_cfgfile_init(filename, empty_key_value_ini);
@@ -239,7 +239,7 @@ test_cfgfile_empty_key_value_pair(void)
 	cfgfile = rte_cfgfile_load(filename, CFG_FLAG_EMPTY_VALUES);
 	close(fd);
 
-	TEST_ASSERT_NOT_NULL(cfgfile, "Failed to parse empty_key_value.ini");
+	TEST_ASSERT_NOT_NULL(cfgfile, "Failed to parse empty_key_value");
 
 	ret = rte_cfgfile_num_sections(cfgfile, NULL, 0);
 	TEST_ASSERT(ret == 1, "Unexpected number of sections: %d", ret);
@@ -256,7 +256,7 @@ test_cfgfile_empty_key_value_pair(void)
 	ret = rte_cfgfile_close(cfgfile);
 	TEST_ASSERT_SUCCESS(ret, "Failed to close cfgfile");
 
-	unlink(filename);
+	remove(filename);
 	return 0;
 }
 
@@ -264,7 +264,7 @@ static int
 test_cfgfile_missing_section(void)
 {
 	struct rte_cfgfile *cfgfile;
-	char filename[] = "/tmp/cfg_missing_section_XXXXXX.ini";
+	char filename[] = "/tmp/cfg_missing_section_XXXXXX";
 	int fd;
 
 	fd = test_cfgfile_init(filename, missing_section_ini);
@@ -274,7 +274,7 @@ test_cfgfile_missing_section(void)
 	close(fd);
 
 	TEST_ASSERT_NULL(cfgfile, "Expected failure did not occur");
-	unlink(filename);
+	remove(filename);
 	return 0;
 }
 
@@ -283,7 +283,7 @@ test_cfgfile_global_properties(void)
 {
 	struct rte_cfgfile *cfgfile;
 	const char *value;
-	char filename[] = "/tmp/cfg_missing_section_XXXXXX.ini";
+	char filename[] = "/tmp/cfg_missing_section_XXXXXX";
 	int fd, ret;
 
 	fd = test_cfgfile_init(filename, missing_section_ini);
@@ -309,7 +309,7 @@ test_cfgfile_global_properties(void)
 	ret = rte_cfgfile_close(cfgfile);
 	TEST_ASSERT_SUCCESS(ret, "Failed to close cfgfile");
 
-	unlink(filename);
+	remove(filename);
 	return 0;
 }
 
@@ -317,7 +317,7 @@ static int
 test_cfgfile_empty_file(void)
 {
 	struct rte_cfgfile *cfgfile;
-	char filename[] = "/tmp/cfg_empty_XXXXXX.ini";
+	char filename[] = "/tmp/cfg_empty_XXXXXX";
 	int fd, ret;
 
 	fd = test_cfgfile_init(filename, empty_ini);
@@ -333,7 +333,7 @@ test_cfgfile_empty_file(void)
 	ret = rte_cfgfile_close(cfgfile);
 	TEST_ASSERT_SUCCESS(ret, "Failed to close cfgfile");
 
-	unlink(filename);
+	remove(filename);
 	return 0;
 }
 
diff --git a/app/test/test_resource.c b/app/test/test_resource.c
deleted file mode 100644
index 05c27db203..0000000000
--- a/app/test/test_resource.c
+++ /dev/null
@@ -1,104 +0,0 @@
-/* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2016 RehiveTech. All rights reserved.
- */
-
-#include <stdio.h>
-#include <string.h>
-
-#include "test.h"
-#include "resource.h"
-
-const char test_resource_dpdk_blob[] = {
-	'\x44', '\x50', '\x44', '\x4b', '\x00'
-};
-
-REGISTER_RESOURCE(test_resource_dpdk,
-		test_resource_dpdk_blob, test_resource_dpdk_blob + 4);
-
-static int test_resource_dpdk(void)
-{
-	const struct resource *r;
-
-	r = resource_find("test_resource_dpdk");
-	TEST_ASSERT_NOT_NULL(r, "Could not find test_resource_dpdk");
-	TEST_ASSERT(!strcmp(r->name, "test_resource_dpdk"),
-			"Found resource %s, expected test_resource_dpdk",
-			r->name);
-
-	TEST_ASSERT(!strncmp("DPDK", r->begin, 4),
-			"Unexpected payload: %.4s...", r->begin);
-
-	return 0;
-}
-
-REGISTER_LINKED_RESOURCE(test_resource_c);
-
-static int test_resource_c(void)
-{
-	const struct resource *r;
-	FILE *f;
-
-	r = resource_find("test_resource_c");
-	TEST_ASSERT_NOT_NULL(r, "No test_resource_c found");
-	TEST_ASSERT(!strcmp(r->name, "test_resource_c"),
-			"Found resource %s, expected test_resource_c",
-			r->name);
-
-	TEST_ASSERT_SUCCESS(resource_fwrite_file(r, "test_resource.c"),
-			"Failed to write file %s", r->name);
-
-	f = fopen("test_resource.c", "r");
-	TEST_ASSERT_NOT_NULL(f,
-			"Missing extracted file resource.c");
-	fclose(f);
-	remove("test_resource.c");
-
-	return 0;
-}
-
-#ifdef RTE_APP_TEST_RESOURCE_TAR
-REGISTER_LINKED_RESOURCE(test_resource_tar);
-
-static int test_resource_tar(void)
-{
-	const struct resource *r;
-	FILE *f;
-
-	r = resource_find("test_resource_tar");
-	TEST_ASSERT_NOT_NULL(r, "No test_resource_tar found");
-	TEST_ASSERT(!strcmp(r->name, "test_resource_tar"),
-			"Found resource %s, expected test_resource_tar",
-			r->name);
-
-	TEST_ASSERT_SUCCESS(resource_untar(r),
-			"Failed to to untar %s", r->name);
-
-	f = fopen("test_resource.c", "r");
-	TEST_ASSERT_NOT_NULL(f,
-			"Missing extracted file test_resource.c");
-	fclose(f);
-
-	TEST_ASSERT_SUCCESS(resource_rm_by_tar(r),
-			"Failed to remove extracted contents of %s", r->name);
-	return 0;
-}
-
-#endif /* RTE_APP_TEST_RESOURCE_TAR */
-
-static int test_resource(void)
-{
-	if (test_resource_dpdk())
-		return -1;
-
-	if (test_resource_c())
-		return -1;
-
-#ifdef RTE_APP_TEST_RESOURCE_TAR
-	if (test_resource_tar())
-		return -1;
-#endif /* RTE_APP_TEST_RESOURCE_TAR */
-
-	return 0;
-}
-
-REGISTER_TEST_COMMAND(resource_autotest, test_resource);
-- 
2.43.0


^ permalink raw reply	[flat|nested] 34+ messages in thread

* [PATCH v3 0/3] restore lost tests for rte_cfgfile
  2024-07-30 22:51 [PATCH 0/3] restore cfgfile library tests Stephen Hemminger
                   ` (3 preceding siblings ...)
  2024-07-31  4:20 ` [PATCH v2 0/3] restore cfgfile library tests Stephen Hemminger
@ 2024-07-31 17:35 ` Stephen Hemminger
  2024-07-31 17:35   ` [PATCH v3 1/3] buildtools: add helper to convert text file to header Stephen Hemminger
                     ` (2 more replies)
  2024-08-01 17:29 ` [PATCH v4 0/3] restore lost " Stephen Hemminger
                   ` (2 subsequent siblings)
  7 siblings, 3 replies; 34+ messages in thread
From: Stephen Hemminger @ 2024-07-31 17:35 UTC (permalink / raw)
  To: dev; +Cc: Stephen Hemminger

The cfgfile tests did not get built since conversion to meson
and they used an awkward way to manage the test data.

This patchset converts the tests to use a helper to take
text file and make it into a C header. Then use the C header
to generate temporary files as needed.

v3 - change creation of temp file to support Windows

Stephen Hemminger (3):
  buildtools: add helper to convert text file to header
  test: remove unused resource API
  test: restore cfgfile tests

 app/meson.build                    |   3 +-
 app/test/meson.build               |   8 +-
 app/test/resource.c                | 276 -----------------------------
 app/test/resource.h                | 106 -----------
 app/test/test_cfgfile.c            | 153 ++++++++++------
 app/test/test_cfgfiles/meson.build |  19 ++
 app/test/test_resource.c           | 104 -----------
 buildtools/gen-header.py           |  36 ++++
 buildtools/meson.build             |   2 +-
 9 files changed, 166 insertions(+), 541 deletions(-)
 delete mode 100644 app/test/resource.c
 delete mode 100644 app/test/resource.h
 create mode 100644 app/test/test_cfgfiles/meson.build
 delete mode 100644 app/test/test_resource.c
 create mode 100644 buildtools/gen-header.py

-- 
2.43.0


^ permalink raw reply	[flat|nested] 34+ messages in thread

* [PATCH v3 1/3] buildtools: add helper to convert text file to header
  2024-07-31 17:35 ` [PATCH v3 0/3] restore lost tests for rte_cfgfile Stephen Hemminger
@ 2024-07-31 17:35   ` Stephen Hemminger
  2024-07-31 17:35   ` [PATCH v3 2/3] test: remove unused resource API Stephen Hemminger
  2024-07-31 17:35   ` [PATCH v3 3/3] test: restore cfgfile tests Stephen Hemminger
  2 siblings, 0 replies; 34+ messages in thread
From: Stephen Hemminger @ 2024-07-31 17:35 UTC (permalink / raw)
  To: dev; +Cc: Stephen Hemminger

Simple script to read a file and make it into a initialized
C string in a header file.

Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
 buildtools/gen-header.py | 36 ++++++++++++++++++++++++++++++++++++
 buildtools/meson.build   |  2 +-
 2 files changed, 37 insertions(+), 1 deletion(-)
 create mode 100644 buildtools/gen-header.py

diff --git a/buildtools/gen-header.py b/buildtools/gen-header.py
new file mode 100644
index 0000000000..06e645863c
--- /dev/null
+++ b/buildtools/gen-header.py
@@ -0,0 +1,36 @@
+#! /usr/bin/env python3
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright (c) 2023 Stephen Hemminger <stephen@networkplumber.org>
+
+"""
+Script to read a text file and convert it into a header file.
+"""
+import sys
+import os
+
+
+def main():
+    '''program main function'''
+    print(f'/* File autogenerated by {sys.argv[0]} */')
+    for path in sys.argv[1:]:
+        name = os.path.basename(path)
+        print()
+        print(f'/* generated from {name} */')
+        with open(path, "r") as f:
+            array = name.replace(".", "_")
+            print(f'static const char {array}[] = ' + '{')
+            line = f.readline()
+
+            # make sure empty string is null terminated
+            if not line:
+                print('    ""')
+
+            while line:
+                s = repr(line)
+                print('    {}'.format(s.replace("'", '"')))
+                line = f.readline()
+            print('};')
+
+
+if __name__ == "__main__":
+    main()
diff --git a/buildtools/meson.build b/buildtools/meson.build
index 3adf34e1a8..bc818a71d5 100644
--- a/buildtools/meson.build
+++ b/buildtools/meson.build
@@ -24,6 +24,7 @@ get_numa_count_cmd = py3 + files('get-numa-count.py')
 get_test_suites_cmd = py3 + files('get-test-suites.py')
 has_hugepages_cmd = py3 + files('has-hugepages.py')
 cmdline_gen_cmd = py3 + files('dpdk-cmdline-gen.py')
+header_gen_cmd = py3 + files('gen-header.py')
 
 # install any build tools that end-users might want also
 install_data([
@@ -48,4 +49,3 @@ else
     pmdinfo += 'ar'
     pmdinfogen += 'elf'
 endif
-
-- 
2.43.0


^ permalink raw reply	[flat|nested] 34+ messages in thread

* [PATCH v3 2/3] test: remove unused resource API
  2024-07-31 17:35 ` [PATCH v3 0/3] restore lost tests for rte_cfgfile Stephen Hemminger
  2024-07-31 17:35   ` [PATCH v3 1/3] buildtools: add helper to convert text file to header Stephen Hemminger
@ 2024-07-31 17:35   ` Stephen Hemminger
  2024-07-31 17:35   ` [PATCH v3 3/3] test: restore cfgfile tests Stephen Hemminger
  2 siblings, 0 replies; 34+ messages in thread
From: Stephen Hemminger @ 2024-07-31 17:35 UTC (permalink / raw)
  To: dev; +Cc: Stephen Hemminger

This API was used only for cfgfile tests and was never built
after the conversion to meson. Will be replaced by simpler
method of doing cfgfile tests.

Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
 app/test/meson.build     |   2 -
 app/test/resource.c      | 276 ---------------------------------------
 app/test/resource.h      | 106 ---------------
 app/test/test_resource.c | 104 ---------------
 4 files changed, 488 deletions(-)
 delete mode 100644 app/test/resource.c
 delete mode 100644 app/test/resource.h
 delete mode 100644 app/test/test_resource.c

diff --git a/app/test/meson.build b/app/test/meson.build
index e29258e6ec..62478c0bb6 100644
--- a/app/test/meson.build
+++ b/app/test/meson.build
@@ -20,7 +20,6 @@ test_cryptodev_deps = ['bus_vdev', 'net', 'cryptodev', 'security']
 source_file_deps = {
     # The C files providing functionality to other test cases
     'packet_burst_generator.c': packet_burst_generator_deps,
-#    'resource.c': [],          # unused currently.
     'sample_packet_forward.c': sample_packet_forward_deps,
     'virtual_pmd.c': virtual_pmd_deps,
 
@@ -154,7 +153,6 @@ source_file_deps = {
     'test_reciprocal_division_perf.c': [],
     'test_red.c': ['sched'],
     'test_reorder.c': ['reorder'],
-#    'test_resource.c': [],
     'test_rib.c': ['net', 'rib'],
     'test_rib6.c': ['net', 'rib'],
     'test_ring.c': ['ptr_compress'],
diff --git a/app/test/resource.c b/app/test/resource.c
deleted file mode 100644
index 34465f1668..0000000000
--- a/app/test/resource.c
+++ /dev/null
@@ -1,276 +0,0 @@
-/* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2016 RehiveTech. All rights reserved.
- */
-
-#include <stdio.h>
-#include <string.h>
-#include <errno.h>
-#include <sys/queue.h>
-
-#include <rte_debug.h>
-
-#include "resource.h"
-
-struct resource_list resource_list = TAILQ_HEAD_INITIALIZER(resource_list);
-
-size_t resource_size(const struct resource *r)
-{
-	return r->end - r->begin;
-}
-
-const struct resource *resource_find(const char *name)
-{
-	struct resource *r;
-
-	TAILQ_FOREACH(r, &resource_list, next) {
-		RTE_VERIFY(r->name);
-
-		if (!strcmp(r->name, name))
-			return r;
-	}
-
-	return NULL;
-}
-
-int resource_fwrite(const struct resource *r, FILE *f)
-{
-	const size_t goal = resource_size(r);
-	size_t total = 0;
-
-	while (total < goal) {
-		size_t wlen = fwrite(r->begin + total, 1, goal - total, f);
-		if (wlen == 0) {
-			perror(__func__);
-			return -1;
-		}
-
-		total += wlen;
-	}
-
-	return 0;
-}
-
-int resource_fwrite_file(const struct resource *r, const char *fname)
-{
-	FILE *f;
-	int ret;
-
-	f = fopen(fname, "w");
-	if (f == NULL) {
-		perror(__func__);
-		return -1;
-	}
-
-	ret = resource_fwrite(r, f);
-	fclose(f);
-	return ret;
-}
-
-#ifdef RTE_APP_TEST_RESOURCE_TAR
-#include <archive.h>
-#include <archive_entry.h>
-
-static int do_copy(struct archive *r, struct archive *w)
-{
-	const void *buf;
-	size_t len;
-#if ARCHIVE_VERSION_NUMBER >= 3000000
-	int64_t off;
-#else
-	off_t off;
-#endif
-	int ret;
-
-	while (1) {
-		ret = archive_read_data_block(r, &buf, &len, &off);
-		if (ret == ARCHIVE_RETRY)
-			continue;
-
-		if (ret == ARCHIVE_EOF)
-			return 0;
-
-		if (ret != ARCHIVE_OK)
-			return ret;
-
-		do {
-			ret = archive_write_data_block(w, buf, len, off);
-			if (ret != ARCHIVE_OK && ret != ARCHIVE_RETRY)
-				return ret;
-		} while (ret != ARCHIVE_OK);
-	}
-}
-
-int resource_untar(const struct resource *res)
-{
-	struct archive *r;
-	struct archive *w;
-	struct archive_entry *e;
-	void *p;
-	int flags = 0;
-	int ret;
-
-	p = malloc(resource_size(res));
-	if (p == NULL)
-		rte_panic("Failed to malloc %zu B\n", resource_size(res));
-
-	memcpy(p, res->begin, resource_size(res));
-
-	r = archive_read_new();
-	if (r == NULL) {
-		free(p);
-		return -1;
-	}
-
-	archive_read_support_format_all(r);
-	archive_read_support_filter_all(r);
-
-	w = archive_write_disk_new();
-	if (w == NULL) {
-		archive_read_free(r);
-		free(p);
-		return -1;
-	}
-
-	flags |= ARCHIVE_EXTRACT_PERM;
-	flags |= ARCHIVE_EXTRACT_FFLAGS;
-	archive_write_disk_set_options(w, flags);
-	archive_write_disk_set_standard_lookup(w);
-
-	ret = archive_read_open_memory(r, p, resource_size(res));
-	if (ret != ARCHIVE_OK)
-		goto fail;
-
-	while (1) {
-		ret = archive_read_next_header(r, &e);
-		if (ret == ARCHIVE_EOF)
-			break;
-		if (ret != ARCHIVE_OK)
-			goto fail;
-
-		ret = archive_write_header(w, e);
-		if (ret == ARCHIVE_EOF)
-			break;
-		if (ret != ARCHIVE_OK)
-			goto fail;
-
-		if (archive_entry_size(e) == 0)
-			continue;
-
-		ret = do_copy(r, w);
-		if (ret != ARCHIVE_OK)
-			goto fail;
-
-		ret = archive_write_finish_entry(w);
-		if (ret != ARCHIVE_OK)
-			goto fail;
-	}
-
-	archive_write_free(w);
-	archive_read_free(r);
-	free(p);
-	return 0;
-
-fail:
-	archive_write_free(w);
-	archive_read_free(r);
-	free(p);
-	rte_panic("Failed: %s\n", archive_error_string(r));
-	return -1;
-}
-
-int resource_rm_by_tar(const struct resource *res)
-{
-	struct archive *r;
-	struct archive_entry *e;
-	void *p;
-	int try_again = 1;
-	int attempts = 0;
-	int ret;
-
-	p = malloc(resource_size(res));
-	if (p == NULL)
-		rte_panic("Failed to malloc %zu B\n", resource_size(res));
-
-	memcpy(p, res->begin, resource_size(res));
-
-	/*
-	 * If somebody creates a file somewhere inside the extracted TAR
-	 * hierarchy during a test the resource_rm_by_tar might loop
-	 * infinitely. We prevent this by adding the attempts counter there.
-	 * In normal case, max N iteration is done where N is the depth of
-	 * the file-hierarchy.
-	 */
-	while (try_again && attempts < 10000) {
-		r = archive_read_new();
-		if (r == NULL) {
-			free(p);
-			return -1;
-		}
-
-		archive_read_support_format_all(r);
-		archive_read_support_filter_all(r);
-
-		ret = archive_read_open_memory(r, p, resource_size(res));
-		if (ret != ARCHIVE_OK) {
-			fprintf(stderr, "Failed: %s\n",
-					archive_error_string(r));
-			goto fail;
-		}
-
-		try_again = 0;
-
-		while (1) {
-			ret = archive_read_next_header(r, &e);
-			if (ret == ARCHIVE_EOF)
-				break;
-			if (ret != ARCHIVE_OK)
-				goto fail;
-
-			ret = remove(archive_entry_pathname(e));
-			if (ret < 0) {
-				switch (errno) {
-				case ENOTEMPTY:
-				case EEXIST:
-					try_again = 1;
-					break;
-
-				/* should not usually happen: */
-				case ENOENT:
-				case ENOTDIR:
-				case EROFS:
-					attempts += 1;
-					continue;
-				default:
-					perror("Failed to remove file");
-					goto fail;
-				}
-			}
-		}
-
-		archive_read_free(r);
-		attempts += 1;
-	}
-
-	if (attempts >= 10000) {
-		fprintf(stderr, "Failed to remove archive\n");
-		free(p);
-		return -1;
-	}
-
-	free(p);
-	return 0;
-
-fail:
-	archive_read_free(r);
-	free(p);
-
-	rte_panic("Failed: %s\n", archive_error_string(r));
-	return -1;
-}
-
-#endif /* RTE_APP_TEST_RESOURCE_TAR */
-
-void resource_register(struct resource *r)
-{
-	TAILQ_INSERT_TAIL(&resource_list, r, next);
-}
diff --git a/app/test/resource.h b/app/test/resource.h
deleted file mode 100644
index c75ebd4b5d..0000000000
--- a/app/test/resource.h
+++ /dev/null
@@ -1,106 +0,0 @@
-/* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2016 RehiveTech. All rights reserved.
- */
-
-#ifndef _RESOURCE_H_
-#define _RESOURCE_H_
-
-/**
- * @file
- *
- * Test Resource API
- *
- * Each test can require and use some external resources. Usually, an external
- * resource is a file or a filesystem sub-hierarchy. A resource is included
- * inside the test executable.
- */
-
-#include <sys/queue.h>
-#include <stdio.h>
-#include <stddef.h>
-
-#include <rte_eal.h>
-#include <rte_common.h>
-
-TAILQ_HEAD(resource_list, resource);
-extern struct resource_list resource_list;
-
-/**
- * Representation of a resource. It points to the resource's binary data.
- * The semantics of the binary data are defined by the target test.
- */
-struct resource {
-	const char *name;  /**< Unique name of the resource */
-	const char *begin; /**< Start of resource data */
-	const char *end;   /**< End of resource data */
-	TAILQ_ENTRY(resource) next;
-};
-
-/**
- * @return size of the given resource
- */
-size_t resource_size(const struct resource *r);
-
-/**
- * Find a resource by name in the global list of resources.
- */
-const struct resource *resource_find(const char *name);
-
-/**
- * Write the raw data of the resource to the given file.
- * @return 0 on success
- */
-int resource_fwrite(const struct resource *r, FILE *f);
-
-/**
- * Write the raw data of the resource to the given file given by name.
- * The name is relative to the current working directory.
- * @return 0 on success
- */
-int resource_fwrite_file(const struct resource *r, const char *fname);
-
-/**
- * Treat the given resource as a tar archive. Extract
- * the archive to the current directory.
- */
-int resource_untar(const struct resource *res);
-
-/**
- * Treat the given resource as a tar archive. Remove
- * all files (related to the current directory) listed
- * in the tar archive.
- */
-int resource_rm_by_tar(const struct resource *res);
-
-/**
- * Register a resource in the global list of resources.
- * Not intended for direct use, please check the REGISTER_RESOURCE
- * macro.
- */
-void resource_register(struct resource *r);
-
-/**
- * Definition of a resource linked externally (by means of the used toolchain).
- * Only the base name of the resource is expected. The name refers to the
- * linked pointers beg_<name> and end_<name> provided externally.
- */
-#define REGISTER_LINKED_RESOURCE(n) \
-extern const char beg_ ##n;         \
-extern const char end_ ##n;         \
-REGISTER_RESOURCE(n, &beg_ ##n, &end_ ##n) \
-
-/**
- * Definition of a resource described by its name, and pointers begin, end.
- */
-#define REGISTER_RESOURCE(n, b, e) \
-static struct resource linkres_ ##n = {       \
-	.name = RTE_STR(n),     \
-	.begin = b,             \
-	.end = e,               \
-};                              \
-RTE_INIT(resinitfn_ ##n)	\
-{                               \
-	resource_register(&linkres_ ##n);  \
-}
-
-#endif
diff --git a/app/test/test_resource.c b/app/test/test_resource.c
deleted file mode 100644
index 05c27db203..0000000000
--- a/app/test/test_resource.c
+++ /dev/null
@@ -1,104 +0,0 @@
-/* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2016 RehiveTech. All rights reserved.
- */
-
-#include <stdio.h>
-#include <string.h>
-
-#include "test.h"
-#include "resource.h"
-
-const char test_resource_dpdk_blob[] = {
-	'\x44', '\x50', '\x44', '\x4b', '\x00'
-};
-
-REGISTER_RESOURCE(test_resource_dpdk,
-		test_resource_dpdk_blob, test_resource_dpdk_blob + 4);
-
-static int test_resource_dpdk(void)
-{
-	const struct resource *r;
-
-	r = resource_find("test_resource_dpdk");
-	TEST_ASSERT_NOT_NULL(r, "Could not find test_resource_dpdk");
-	TEST_ASSERT(!strcmp(r->name, "test_resource_dpdk"),
-			"Found resource %s, expected test_resource_dpdk",
-			r->name);
-
-	TEST_ASSERT(!strncmp("DPDK", r->begin, 4),
-			"Unexpected payload: %.4s...", r->begin);
-
-	return 0;
-}
-
-REGISTER_LINKED_RESOURCE(test_resource_c);
-
-static int test_resource_c(void)
-{
-	const struct resource *r;
-	FILE *f;
-
-	r = resource_find("test_resource_c");
-	TEST_ASSERT_NOT_NULL(r, "No test_resource_c found");
-	TEST_ASSERT(!strcmp(r->name, "test_resource_c"),
-			"Found resource %s, expected test_resource_c",
-			r->name);
-
-	TEST_ASSERT_SUCCESS(resource_fwrite_file(r, "test_resource.c"),
-			"Failed to write file %s", r->name);
-
-	f = fopen("test_resource.c", "r");
-	TEST_ASSERT_NOT_NULL(f,
-			"Missing extracted file resource.c");
-	fclose(f);
-	remove("test_resource.c");
-
-	return 0;
-}
-
-#ifdef RTE_APP_TEST_RESOURCE_TAR
-REGISTER_LINKED_RESOURCE(test_resource_tar);
-
-static int test_resource_tar(void)
-{
-	const struct resource *r;
-	FILE *f;
-
-	r = resource_find("test_resource_tar");
-	TEST_ASSERT_NOT_NULL(r, "No test_resource_tar found");
-	TEST_ASSERT(!strcmp(r->name, "test_resource_tar"),
-			"Found resource %s, expected test_resource_tar",
-			r->name);
-
-	TEST_ASSERT_SUCCESS(resource_untar(r),
-			"Failed to to untar %s", r->name);
-
-	f = fopen("test_resource.c", "r");
-	TEST_ASSERT_NOT_NULL(f,
-			"Missing extracted file test_resource.c");
-	fclose(f);
-
-	TEST_ASSERT_SUCCESS(resource_rm_by_tar(r),
-			"Failed to remove extracted contents of %s", r->name);
-	return 0;
-}
-
-#endif /* RTE_APP_TEST_RESOURCE_TAR */
-
-static int test_resource(void)
-{
-	if (test_resource_dpdk())
-		return -1;
-
-	if (test_resource_c())
-		return -1;
-
-#ifdef RTE_APP_TEST_RESOURCE_TAR
-	if (test_resource_tar())
-		return -1;
-#endif /* RTE_APP_TEST_RESOURCE_TAR */
-
-	return 0;
-}
-
-REGISTER_TEST_COMMAND(resource_autotest, test_resource);
-- 
2.43.0


^ permalink raw reply	[flat|nested] 34+ messages in thread

* [PATCH v3 3/3] test: restore cfgfile tests
  2024-07-31 17:35 ` [PATCH v3 0/3] restore lost tests for rte_cfgfile Stephen Hemminger
  2024-07-31 17:35   ` [PATCH v3 1/3] buildtools: add helper to convert text file to header Stephen Hemminger
  2024-07-31 17:35   ` [PATCH v3 2/3] test: remove unused resource API Stephen Hemminger
@ 2024-07-31 17:35   ` Stephen Hemminger
  2 siblings, 0 replies; 34+ messages in thread
From: Stephen Hemminger @ 2024-07-31 17:35 UTC (permalink / raw)
  To: dev; +Cc: Stephen Hemminger

These tests were not built since the conversion to meson.
Instead of using embedded resource functions, put data in include
file and generate temporary file before the test.

Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
 app/meson.build                    |   3 +-
 app/test/meson.build               |   6 +-
 app/test/test_cfgfile.c            | 153 +++++++++++++++++++----------
 app/test/test_cfgfiles/meson.build |  19 ++++
 4 files changed, 129 insertions(+), 52 deletions(-)
 create mode 100644 app/test/test_cfgfiles/meson.build

diff --git a/app/meson.build b/app/meson.build
index 5b2c80c7a1..e2db888ae1 100644
--- a/app/meson.build
+++ b/app/meson.build
@@ -55,6 +55,7 @@ foreach app:apps
     build = true
     reason = '<unknown reason>' # set if build == false to explain
     sources = []
+    resources = []
     includes = []
     cflags = default_cflags
     ldflags = default_ldflags
@@ -115,7 +116,7 @@ foreach app:apps
     endif
 
     exec = executable('dpdk-' + name,
-            sources,
+            [ sources, resources ],
             c_args: cflags,
             link_args: ldflags,
             link_whole: link_libs,
diff --git a/app/test/meson.build b/app/test/meson.build
index 62478c0bb6..b2bb7c36f6 100644
--- a/app/test/meson.build
+++ b/app/test/meson.build
@@ -35,7 +35,7 @@ source_file_deps = {
     'test_bitratestats.c': ['metrics', 'bitratestats', 'ethdev'] + sample_packet_forward_deps,
     'test_bpf.c': ['bpf', 'net'],
     'test_byteorder.c': [],
-#    'test_cfgfile.c': ['cfgfile'],
+    'test_cfgfile.c': ['cfgfile'],
     'test_cksum.c': ['net'],
     'test_cksum_perf.c': ['net'],
     'test_cmdline.c': [],
@@ -261,3 +261,7 @@ if not is_windows
             build_by_default: true,
             install: false)
 endif
+
+subdir('test_cfgfiles')
+
+resources += test_cfgfile_h
diff --git a/app/test/test_cfgfile.c b/app/test/test_cfgfile.c
index a5e3d8699c..7cfcaf348a 100644
--- a/app/test/test_cfgfile.c
+++ b/app/test/test_cfgfile.c
@@ -5,48 +5,54 @@
 #include <stdio.h>
 #include <string.h>
 #include <stdint.h>
-#include <sys/queue.h>
+#include <unistd.h>
+
+#ifdef RTE_EXEC_ENV_WINDOWS
+#include <io.h>
+#endif
 
 #include <rte_cfgfile.h>
 
 #include "test.h"
-#include "resource.h"
-
-
-#define CFG_FILES_ETC "test_cfgfiles/etc"
 
-REGISTER_LINKED_RESOURCE(test_cfgfiles);
+#include "test_cfgfiles.h"
 
 static int
-test_cfgfile_setup(void)
+make_tmp_file(char *filename, const char *prefix, const char *data)
 {
-	const struct resource *r;
-	int ret;
+	size_t len = strlen(data);
+	size_t count;
+	FILE *f;
 
-	r = resource_find("test_cfgfiles");
-	TEST_ASSERT_NOT_NULL(r, "missing resource test_cfgfiles");
+#ifdef RTE_EXEC_ENV_WINDOWS
+	char tempDirName[MAX_PATH - 14];
 
-	ret = resource_untar(r);
-	TEST_ASSERT_SUCCESS(ret, "failed to untar %s", r->name);
+	if (GetTempPathA(sizeof(tempDirName), tempDirName) == 0)
+		return -1;
 
-	return 0;
-}
+	if (GetTempFileNameA(tempDirName, prefix, 0, filename) == 0)
+		return -1;
 
-static int
-test_cfgfile_cleanup(void)
-{
-	const struct resource *r;
-	int ret;
+	f = fopen(filename, "wt");
+#else
+	snprintf(filename, PATH_MAX, "/tmp/%s_XXXXXXX", prefix);
 
-	r = resource_find("test_cfgfiles");
-	TEST_ASSERT_NOT_NULL(r, "missing resource test_cfgfiles");
+	int fd = mkstemp(filename);
+	if (fd < 0)
+		return -1;
 
-	ret = resource_rm_by_tar(r);
-	TEST_ASSERT_SUCCESS(ret, "Failed to delete resource %s", r->name);
+	f = fdopen(fd, "w");
+#endif
+	if (f == NULL)
+		return -1;
 
-	return 0;
+	count = fwrite(data, sizeof(char), len, f);
+	fclose(f);
+
+	return (count == len) ? 0 : -1;
 }
 
+
 static int
 _test_cfgfile_sample(struct rte_cfgfile *cfgfile)
 {
@@ -87,9 +93,13 @@ static int
 test_cfgfile_sample1(void)
 {
 	struct rte_cfgfile *cfgfile;
+	char filename[PATH_MAX];
 	int ret;
 
-	cfgfile = rte_cfgfile_load(CFG_FILES_ETC "/sample1.ini", 0);
+	ret = make_tmp_file(filename, "sample1", sample1_ini);
+	TEST_ASSERT_SUCCESS(ret, "Failed to setup temp file");
+
+	cfgfile = rte_cfgfile_load(filename, 0);
 	TEST_ASSERT_NOT_NULL(cfgfile, "Failed to load config file");
 
 	ret = _test_cfgfile_sample(cfgfile);
@@ -98,6 +108,8 @@ test_cfgfile_sample1(void)
 	ret = rte_cfgfile_close(cfgfile);
 	TEST_ASSERT_SUCCESS(ret, "Failed to close cfgfile");
 
+	remove(filename);
+
 	return 0;
 }
 
@@ -106,15 +118,18 @@ test_cfgfile_sample2(void)
 {
 	struct rte_cfgfile_parameters params;
 	struct rte_cfgfile *cfgfile;
+	char filename[PATH_MAX];
 	int ret;
 
+	ret = make_tmp_file(filename, "sample2", sample2_ini);
+	TEST_ASSERT_SUCCESS(ret, "Failed to setup temp file");
+
 	/* override comment character */
 	memset(&params, 0, sizeof(params));
 	params.comment_character = '#';
 
-	cfgfile = rte_cfgfile_load_with_params(CFG_FILES_ETC "/sample2.ini", 0,
-					       &params);
-	TEST_ASSERT_NOT_NULL(cfgfile, "Failed to parse sample2.ini");
+	cfgfile = rte_cfgfile_load_with_params(filename, 0, &params);
+	TEST_ASSERT_NOT_NULL(cfgfile, "Failed to parse sample2");
 
 	ret = _test_cfgfile_sample(cfgfile);
 	TEST_ASSERT_SUCCESS(ret, "Failed to validate sample file: %d", ret);
@@ -122,6 +137,8 @@ test_cfgfile_sample2(void)
 	ret = rte_cfgfile_close(cfgfile);
 	TEST_ASSERT_SUCCESS(ret, "Failed to close cfgfile");
 
+	remove(filename);
+
 	return 0;
 }
 
@@ -129,10 +146,14 @@ static int
 test_cfgfile_realloc_sections(void)
 {
 	struct rte_cfgfile *cfgfile;
+	char filename[PATH_MAX];
 	int ret;
 	const char *value;
 
-	cfgfile = rte_cfgfile_load(CFG_FILES_ETC "/realloc_sections.ini", 0);
+	ret = make_tmp_file(filename, "realloc", realloc_sections_ini);
+	TEST_ASSERT_SUCCESS(ret, "Failed to setup temp file");
+
+	cfgfile = rte_cfgfile_load(filename, 0);
 	TEST_ASSERT_NOT_NULL(cfgfile, "Failed to load config file");
 
 	ret = rte_cfgfile_num_sections(cfgfile, NULL, 0);
@@ -152,13 +173,15 @@ test_cfgfile_realloc_sections(void)
 	TEST_ASSERT(strcmp("value8_section9", value) == 0,
 		    "key unexpected value: %s", value);
 
-	ret = rte_cfgfile_save(cfgfile, "/tmp/cfgfile_save.ini");
+	ret = rte_cfgfile_save(cfgfile, "/tmp/cfg_save.ini");
 	TEST_ASSERT_SUCCESS(ret, "Failed to save *.ini file");
-	remove("/tmp/cfgfile_save.ini");
+	remove("/tmp/cfg_save.ini");
 
 	ret = rte_cfgfile_close(cfgfile);
 	TEST_ASSERT_SUCCESS(ret, "Failed to close cfgfile");
 
+	remove(filename);
+
 	return 0;
 }
 
@@ -166,10 +189,16 @@ static int
 test_cfgfile_invalid_section_header(void)
 {
 	struct rte_cfgfile *cfgfile;
+	char filename[PATH_MAX];
+	int ret;
+
+	ret = make_tmp_file(filename, "invalid", invalid_section_ini);
+	TEST_ASSERT_SUCCESS(ret, "Failed to setup temp file");
 
-	cfgfile = rte_cfgfile_load(CFG_FILES_ETC "/invalid_section.ini", 0);
+	cfgfile = rte_cfgfile_load(filename, 0);
 	TEST_ASSERT_NULL(cfgfile, "Expected failure did not occur");
 
+	remove(filename);
 	return 0;
 }
 
@@ -178,15 +207,20 @@ test_cfgfile_invalid_comment(void)
 {
 	struct rte_cfgfile_parameters params;
 	struct rte_cfgfile *cfgfile;
+	char filename[PATH_MAX];
+	int ret;
 
 	/* override comment character with an invalid one */
 	memset(&params, 0, sizeof(params));
 	params.comment_character = '$';
 
-	cfgfile = rte_cfgfile_load_with_params(CFG_FILES_ETC "/sample2.ini", 0,
-					       &params);
+	ret = make_tmp_file(filename, "sample2", sample2_ini);
+	TEST_ASSERT_SUCCESS(ret, "Failed to setup temp file");
+
+	cfgfile = rte_cfgfile_load_with_params(filename, 0, &params);
 	TEST_ASSERT_NULL(cfgfile, "Expected failure did not occur");
 
+	remove(filename);
 	return 0;
 }
 
@@ -194,10 +228,16 @@ static int
 test_cfgfile_invalid_key_value_pair(void)
 {
 	struct rte_cfgfile *cfgfile;
+	char filename[PATH_MAX];
+	int ret;
+
+	ret = make_tmp_file(filename, "empty_key", empty_key_value_ini);
+	TEST_ASSERT_SUCCESS(ret, "Failed to setup temp file");
 
-	cfgfile = rte_cfgfile_load(CFG_FILES_ETC "/empty_key_value.ini", 0);
+	cfgfile = rte_cfgfile_load(filename, 0);
 	TEST_ASSERT_NULL(cfgfile, "Expected failure did not occur");
 
+	remove(filename);
 	return 0;
 }
 
@@ -206,11 +246,14 @@ test_cfgfile_empty_key_value_pair(void)
 {
 	struct rte_cfgfile *cfgfile;
 	const char *value;
+	char filename[PATH_MAX];
 	int ret;
 
-	cfgfile = rte_cfgfile_load(CFG_FILES_ETC "/empty_key_value.ini",
-				   CFG_FLAG_EMPTY_VALUES);
-	TEST_ASSERT_NOT_NULL(cfgfile, "Failed to parse empty_key_value.ini");
+	ret = make_tmp_file(filename, "empty_key_value", empty_key_value_ini);
+	TEST_ASSERT_SUCCESS(ret, "Failed to setup temp file");
+
+	cfgfile = rte_cfgfile_load(filename, CFG_FLAG_EMPTY_VALUES);
+	TEST_ASSERT_NOT_NULL(cfgfile, "Failed to parse empty_key_value");
 
 	ret = rte_cfgfile_num_sections(cfgfile, NULL, 0);
 	TEST_ASSERT(ret == 1, "Unexpected number of sections: %d", ret);
@@ -227,6 +270,7 @@ test_cfgfile_empty_key_value_pair(void)
 	ret = rte_cfgfile_close(cfgfile);
 	TEST_ASSERT_SUCCESS(ret, "Failed to close cfgfile");
 
+	remove(filename);
 	return 0;
 }
 
@@ -234,10 +278,16 @@ static int
 test_cfgfile_missing_section(void)
 {
 	struct rte_cfgfile *cfgfile;
+	char filename[PATH_MAX];
+	int ret;
+
+	ret = make_tmp_file(filename, "missing_section", missing_section_ini);
+	TEST_ASSERT_SUCCESS(ret, "Failed to setup temp file");
 
-	cfgfile = rte_cfgfile_load(CFG_FILES_ETC "/missing_section.ini", 0);
+	cfgfile = rte_cfgfile_load(filename, 0);
 	TEST_ASSERT_NULL(cfgfile, "Expected failure did not occur");
 
+	remove(filename);
 	return 0;
 }
 
@@ -246,10 +296,13 @@ test_cfgfile_global_properties(void)
 {
 	struct rte_cfgfile *cfgfile;
 	const char *value;
+	char filename[PATH_MAX];
 	int ret;
 
-	cfgfile = rte_cfgfile_load(CFG_FILES_ETC "/missing_section.ini",
-				   CFG_FLAG_GLOBAL_SECTION);
+	ret = make_tmp_file(filename, "missing_section", missing_section_ini);
+	TEST_ASSERT_SUCCESS(ret, "Failed to setup temp file");
+
+	cfgfile = rte_cfgfile_load(filename, CFG_FLAG_GLOBAL_SECTION);
 	TEST_ASSERT_NOT_NULL(cfgfile, "Failed to load config file");
 
 	ret = rte_cfgfile_num_sections(cfgfile, NULL, 0);
@@ -268,6 +321,7 @@ test_cfgfile_global_properties(void)
 	ret = rte_cfgfile_close(cfgfile);
 	TEST_ASSERT_SUCCESS(ret, "Failed to close cfgfile");
 
+	remove(filename);
 	return 0;
 }
 
@@ -275,9 +329,13 @@ static int
 test_cfgfile_empty_file(void)
 {
 	struct rte_cfgfile *cfgfile;
+	char filename[PATH_MAX];
 	int ret;
 
-	cfgfile = rte_cfgfile_load(CFG_FILES_ETC "/empty.ini", 0);
+	ret = make_tmp_file(filename, "empty", empty_ini);
+	TEST_ASSERT_SUCCESS(ret, "Failed to setup temp file");
+
+	cfgfile = rte_cfgfile_load(filename, 0);
 	TEST_ASSERT_NOT_NULL(cfgfile, "Failed to load config file");
 
 	ret = rte_cfgfile_num_sections(cfgfile, NULL, 0);
@@ -286,15 +344,13 @@ test_cfgfile_empty_file(void)
 	ret = rte_cfgfile_close(cfgfile);
 	TEST_ASSERT_SUCCESS(ret, "Failed to close cfgfile");
 
+	remove(filename);
 	return 0;
 }
 
 static int
 test_cfgfile(void)
 {
-	if (test_cfgfile_setup())
-		return -1;
-
 	if (test_cfgfile_sample1())
 		return -1;
 
@@ -325,10 +381,7 @@ test_cfgfile(void)
 	if (test_cfgfile_empty_file())
 		return -1;
 
-	if (test_cfgfile_cleanup())
-		return -1;
-
 	return 0;
 }
 
-REGISTER_TEST_COMMAND(cfgfile_autotest, test_cfgfile);
+REGISTER_FAST_TEST(cfgfile_autotest, true, true, test_cfgfile);
diff --git a/app/test/test_cfgfiles/meson.build b/app/test/test_cfgfiles/meson.build
new file mode 100644
index 0000000000..068b61044a
--- /dev/null
+++ b/app/test/test_cfgfiles/meson.build
@@ -0,0 +1,19 @@
+# SPDX-License-Identifier: BSD-3-Clause
+
+test_cfgfiles = files(
+    'etc/empty.ini',
+    'etc/empty_key_value.ini',
+    'etc/invalid_section.ini',
+    'etc/line_too_long.ini',
+    'etc/missing_section.ini',
+    'etc/realloc_sections.ini',
+    'etc/sample1.ini',
+    'etc/sample2.ini',
+)
+
+# generate the header file used in cfgfile test
+test_cfgfile_h = custom_target('test_cfgfile',
+                          output: 'test_cfgfiles.h',
+                          input: test_cfgfiles,
+                          capture: true,
+                          command: [ header_gen_cmd, '@INPUT@'])
-- 
2.43.0


^ permalink raw reply	[flat|nested] 34+ messages in thread

* [PATCH v4 0/3] restore lost cfgfile tests
  2024-07-30 22:51 [PATCH 0/3] restore cfgfile library tests Stephen Hemminger
                   ` (4 preceding siblings ...)
  2024-07-31 17:35 ` [PATCH v3 0/3] restore lost tests for rte_cfgfile Stephen Hemminger
@ 2024-08-01 17:29 ` Stephen Hemminger
  2024-08-01 17:29   ` [PATCH v4 1/3] buildtools: add helper to convert text file to header Stephen Hemminger
                     ` (2 more replies)
  2024-08-02 16:44 ` [PATCH v5 0/4] restore unused " Stephen Hemminger
  2024-08-13 15:57 ` [PATCH v6 0/4] test: restore cfgfile lib tests Stephen Hemminger
  7 siblings, 3 replies; 34+ messages in thread
From: Stephen Hemminger @ 2024-08-01 17:29 UTC (permalink / raw)
  To: dev; +Cc: Stephen Hemminger

The cfgfile tests did not get built since conversion to meson
and they used an awkward way to manage the test data.

This patchset converts the tests to use a helper to take
text file and make it into a C header. Then use the C header
to generate temporary files as needed.

v4 - add special treatment for temp directory in Windows
     the test obviously never ran before on Windows.

Stephen Hemminger (3):
  buildtools: add helper to convert text file to header
  test: remove unused resource API
  test: restore cfgfile tests

 app/meson.build                    |   3 +-
 app/test/meson.build               |   8 +-
 app/test/resource.c                | 276 -----------------------------
 app/test/resource.h                | 106 -----------
 app/test/test_cfgfile.c            | 153 ++++++++++------
 app/test/test_cfgfiles/meson.build |  19 ++
 app/test/test_resource.c           | 104 -----------
 buildtools/gen-header.py           |  36 ++++
 buildtools/meson.build             |   2 +-
 9 files changed, 166 insertions(+), 541 deletions(-)
 delete mode 100644 app/test/resource.c
 delete mode 100644 app/test/resource.h
 create mode 100644 app/test/test_cfgfiles/meson.build
 delete mode 100644 app/test/test_resource.c
 create mode 100644 buildtools/gen-header.py

-- 
2.43.0


^ permalink raw reply	[flat|nested] 34+ messages in thread

* [PATCH v4 1/3] buildtools: add helper to convert text file to header
  2024-08-01 17:29 ` [PATCH v4 0/3] restore lost " Stephen Hemminger
@ 2024-08-01 17:29   ` Stephen Hemminger
  2024-08-02 15:15     ` Bruce Richardson
  2024-08-01 17:29   ` [PATCH v4 2/3] test: remove unused resource API Stephen Hemminger
  2024-08-01 17:29   ` [PATCH v4 3/3] test: restore cfgfile tests Stephen Hemminger
  2 siblings, 1 reply; 34+ messages in thread
From: Stephen Hemminger @ 2024-08-01 17:29 UTC (permalink / raw)
  To: dev; +Cc: Stephen Hemminger

Simple script to read a file and make it into a initialized
C string in a header file.

Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
 buildtools/gen-header.py | 36 ++++++++++++++++++++++++++++++++++++
 buildtools/meson.build   |  2 +-
 2 files changed, 37 insertions(+), 1 deletion(-)
 create mode 100644 buildtools/gen-header.py

diff --git a/buildtools/gen-header.py b/buildtools/gen-header.py
new file mode 100644
index 0000000000..06e645863c
--- /dev/null
+++ b/buildtools/gen-header.py
@@ -0,0 +1,36 @@
+#! /usr/bin/env python3
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright (c) 2023 Stephen Hemminger <stephen@networkplumber.org>
+
+"""
+Script to read a text file and convert it into a header file.
+"""
+import sys
+import os
+
+
+def main():
+    '''program main function'''
+    print(f'/* File autogenerated by {sys.argv[0]} */')
+    for path in sys.argv[1:]:
+        name = os.path.basename(path)
+        print()
+        print(f'/* generated from {name} */')
+        with open(path, "r") as f:
+            array = name.replace(".", "_")
+            print(f'static const char {array}[] = ' + '{')
+            line = f.readline()
+
+            # make sure empty string is null terminated
+            if not line:
+                print('    ""')
+
+            while line:
+                s = repr(line)
+                print('    {}'.format(s.replace("'", '"')))
+                line = f.readline()
+            print('};')
+
+
+if __name__ == "__main__":
+    main()
diff --git a/buildtools/meson.build b/buildtools/meson.build
index 3adf34e1a8..bc818a71d5 100644
--- a/buildtools/meson.build
+++ b/buildtools/meson.build
@@ -24,6 +24,7 @@ get_numa_count_cmd = py3 + files('get-numa-count.py')
 get_test_suites_cmd = py3 + files('get-test-suites.py')
 has_hugepages_cmd = py3 + files('has-hugepages.py')
 cmdline_gen_cmd = py3 + files('dpdk-cmdline-gen.py')
+header_gen_cmd = py3 + files('gen-header.py')
 
 # install any build tools that end-users might want also
 install_data([
@@ -48,4 +49,3 @@ else
     pmdinfo += 'ar'
     pmdinfogen += 'elf'
 endif
-
-- 
2.43.0


^ permalink raw reply	[flat|nested] 34+ messages in thread

* [PATCH v4 2/3] test: remove unused resource API
  2024-08-01 17:29 ` [PATCH v4 0/3] restore lost " Stephen Hemminger
  2024-08-01 17:29   ` [PATCH v4 1/3] buildtools: add helper to convert text file to header Stephen Hemminger
@ 2024-08-01 17:29   ` Stephen Hemminger
  2024-08-02 15:16     ` Bruce Richardson
  2024-08-01 17:29   ` [PATCH v4 3/3] test: restore cfgfile tests Stephen Hemminger
  2 siblings, 1 reply; 34+ messages in thread
From: Stephen Hemminger @ 2024-08-01 17:29 UTC (permalink / raw)
  To: dev; +Cc: Stephen Hemminger

This API was used only for cfgfile tests and was never built
after the conversion to meson. Will be replaced by simpler
method of doing cfgfile tests.

Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
 app/test/meson.build     |   2 -
 app/test/resource.c      | 276 ---------------------------------------
 app/test/resource.h      | 106 ---------------
 app/test/test_resource.c | 104 ---------------
 4 files changed, 488 deletions(-)
 delete mode 100644 app/test/resource.c
 delete mode 100644 app/test/resource.h
 delete mode 100644 app/test/test_resource.c

diff --git a/app/test/meson.build b/app/test/meson.build
index e29258e6ec..62478c0bb6 100644
--- a/app/test/meson.build
+++ b/app/test/meson.build
@@ -20,7 +20,6 @@ test_cryptodev_deps = ['bus_vdev', 'net', 'cryptodev', 'security']
 source_file_deps = {
     # The C files providing functionality to other test cases
     'packet_burst_generator.c': packet_burst_generator_deps,
-#    'resource.c': [],          # unused currently.
     'sample_packet_forward.c': sample_packet_forward_deps,
     'virtual_pmd.c': virtual_pmd_deps,
 
@@ -154,7 +153,6 @@ source_file_deps = {
     'test_reciprocal_division_perf.c': [],
     'test_red.c': ['sched'],
     'test_reorder.c': ['reorder'],
-#    'test_resource.c': [],
     'test_rib.c': ['net', 'rib'],
     'test_rib6.c': ['net', 'rib'],
     'test_ring.c': ['ptr_compress'],
diff --git a/app/test/resource.c b/app/test/resource.c
deleted file mode 100644
index 34465f1668..0000000000
--- a/app/test/resource.c
+++ /dev/null
@@ -1,276 +0,0 @@
-/* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2016 RehiveTech. All rights reserved.
- */
-
-#include <stdio.h>
-#include <string.h>
-#include <errno.h>
-#include <sys/queue.h>
-
-#include <rte_debug.h>
-
-#include "resource.h"
-
-struct resource_list resource_list = TAILQ_HEAD_INITIALIZER(resource_list);
-
-size_t resource_size(const struct resource *r)
-{
-	return r->end - r->begin;
-}
-
-const struct resource *resource_find(const char *name)
-{
-	struct resource *r;
-
-	TAILQ_FOREACH(r, &resource_list, next) {
-		RTE_VERIFY(r->name);
-
-		if (!strcmp(r->name, name))
-			return r;
-	}
-
-	return NULL;
-}
-
-int resource_fwrite(const struct resource *r, FILE *f)
-{
-	const size_t goal = resource_size(r);
-	size_t total = 0;
-
-	while (total < goal) {
-		size_t wlen = fwrite(r->begin + total, 1, goal - total, f);
-		if (wlen == 0) {
-			perror(__func__);
-			return -1;
-		}
-
-		total += wlen;
-	}
-
-	return 0;
-}
-
-int resource_fwrite_file(const struct resource *r, const char *fname)
-{
-	FILE *f;
-	int ret;
-
-	f = fopen(fname, "w");
-	if (f == NULL) {
-		perror(__func__);
-		return -1;
-	}
-
-	ret = resource_fwrite(r, f);
-	fclose(f);
-	return ret;
-}
-
-#ifdef RTE_APP_TEST_RESOURCE_TAR
-#include <archive.h>
-#include <archive_entry.h>
-
-static int do_copy(struct archive *r, struct archive *w)
-{
-	const void *buf;
-	size_t len;
-#if ARCHIVE_VERSION_NUMBER >= 3000000
-	int64_t off;
-#else
-	off_t off;
-#endif
-	int ret;
-
-	while (1) {
-		ret = archive_read_data_block(r, &buf, &len, &off);
-		if (ret == ARCHIVE_RETRY)
-			continue;
-
-		if (ret == ARCHIVE_EOF)
-			return 0;
-
-		if (ret != ARCHIVE_OK)
-			return ret;
-
-		do {
-			ret = archive_write_data_block(w, buf, len, off);
-			if (ret != ARCHIVE_OK && ret != ARCHIVE_RETRY)
-				return ret;
-		} while (ret != ARCHIVE_OK);
-	}
-}
-
-int resource_untar(const struct resource *res)
-{
-	struct archive *r;
-	struct archive *w;
-	struct archive_entry *e;
-	void *p;
-	int flags = 0;
-	int ret;
-
-	p = malloc(resource_size(res));
-	if (p == NULL)
-		rte_panic("Failed to malloc %zu B\n", resource_size(res));
-
-	memcpy(p, res->begin, resource_size(res));
-
-	r = archive_read_new();
-	if (r == NULL) {
-		free(p);
-		return -1;
-	}
-
-	archive_read_support_format_all(r);
-	archive_read_support_filter_all(r);
-
-	w = archive_write_disk_new();
-	if (w == NULL) {
-		archive_read_free(r);
-		free(p);
-		return -1;
-	}
-
-	flags |= ARCHIVE_EXTRACT_PERM;
-	flags |= ARCHIVE_EXTRACT_FFLAGS;
-	archive_write_disk_set_options(w, flags);
-	archive_write_disk_set_standard_lookup(w);
-
-	ret = archive_read_open_memory(r, p, resource_size(res));
-	if (ret != ARCHIVE_OK)
-		goto fail;
-
-	while (1) {
-		ret = archive_read_next_header(r, &e);
-		if (ret == ARCHIVE_EOF)
-			break;
-		if (ret != ARCHIVE_OK)
-			goto fail;
-
-		ret = archive_write_header(w, e);
-		if (ret == ARCHIVE_EOF)
-			break;
-		if (ret != ARCHIVE_OK)
-			goto fail;
-
-		if (archive_entry_size(e) == 0)
-			continue;
-
-		ret = do_copy(r, w);
-		if (ret != ARCHIVE_OK)
-			goto fail;
-
-		ret = archive_write_finish_entry(w);
-		if (ret != ARCHIVE_OK)
-			goto fail;
-	}
-
-	archive_write_free(w);
-	archive_read_free(r);
-	free(p);
-	return 0;
-
-fail:
-	archive_write_free(w);
-	archive_read_free(r);
-	free(p);
-	rte_panic("Failed: %s\n", archive_error_string(r));
-	return -1;
-}
-
-int resource_rm_by_tar(const struct resource *res)
-{
-	struct archive *r;
-	struct archive_entry *e;
-	void *p;
-	int try_again = 1;
-	int attempts = 0;
-	int ret;
-
-	p = malloc(resource_size(res));
-	if (p == NULL)
-		rte_panic("Failed to malloc %zu B\n", resource_size(res));
-
-	memcpy(p, res->begin, resource_size(res));
-
-	/*
-	 * If somebody creates a file somewhere inside the extracted TAR
-	 * hierarchy during a test the resource_rm_by_tar might loop
-	 * infinitely. We prevent this by adding the attempts counter there.
-	 * In normal case, max N iteration is done where N is the depth of
-	 * the file-hierarchy.
-	 */
-	while (try_again && attempts < 10000) {
-		r = archive_read_new();
-		if (r == NULL) {
-			free(p);
-			return -1;
-		}
-
-		archive_read_support_format_all(r);
-		archive_read_support_filter_all(r);
-
-		ret = archive_read_open_memory(r, p, resource_size(res));
-		if (ret != ARCHIVE_OK) {
-			fprintf(stderr, "Failed: %s\n",
-					archive_error_string(r));
-			goto fail;
-		}
-
-		try_again = 0;
-
-		while (1) {
-			ret = archive_read_next_header(r, &e);
-			if (ret == ARCHIVE_EOF)
-				break;
-			if (ret != ARCHIVE_OK)
-				goto fail;
-
-			ret = remove(archive_entry_pathname(e));
-			if (ret < 0) {
-				switch (errno) {
-				case ENOTEMPTY:
-				case EEXIST:
-					try_again = 1;
-					break;
-
-				/* should not usually happen: */
-				case ENOENT:
-				case ENOTDIR:
-				case EROFS:
-					attempts += 1;
-					continue;
-				default:
-					perror("Failed to remove file");
-					goto fail;
-				}
-			}
-		}
-
-		archive_read_free(r);
-		attempts += 1;
-	}
-
-	if (attempts >= 10000) {
-		fprintf(stderr, "Failed to remove archive\n");
-		free(p);
-		return -1;
-	}
-
-	free(p);
-	return 0;
-
-fail:
-	archive_read_free(r);
-	free(p);
-
-	rte_panic("Failed: %s\n", archive_error_string(r));
-	return -1;
-}
-
-#endif /* RTE_APP_TEST_RESOURCE_TAR */
-
-void resource_register(struct resource *r)
-{
-	TAILQ_INSERT_TAIL(&resource_list, r, next);
-}
diff --git a/app/test/resource.h b/app/test/resource.h
deleted file mode 100644
index c75ebd4b5d..0000000000
--- a/app/test/resource.h
+++ /dev/null
@@ -1,106 +0,0 @@
-/* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2016 RehiveTech. All rights reserved.
- */
-
-#ifndef _RESOURCE_H_
-#define _RESOURCE_H_
-
-/**
- * @file
- *
- * Test Resource API
- *
- * Each test can require and use some external resources. Usually, an external
- * resource is a file or a filesystem sub-hierarchy. A resource is included
- * inside the test executable.
- */
-
-#include <sys/queue.h>
-#include <stdio.h>
-#include <stddef.h>
-
-#include <rte_eal.h>
-#include <rte_common.h>
-
-TAILQ_HEAD(resource_list, resource);
-extern struct resource_list resource_list;
-
-/**
- * Representation of a resource. It points to the resource's binary data.
- * The semantics of the binary data are defined by the target test.
- */
-struct resource {
-	const char *name;  /**< Unique name of the resource */
-	const char *begin; /**< Start of resource data */
-	const char *end;   /**< End of resource data */
-	TAILQ_ENTRY(resource) next;
-};
-
-/**
- * @return size of the given resource
- */
-size_t resource_size(const struct resource *r);
-
-/**
- * Find a resource by name in the global list of resources.
- */
-const struct resource *resource_find(const char *name);
-
-/**
- * Write the raw data of the resource to the given file.
- * @return 0 on success
- */
-int resource_fwrite(const struct resource *r, FILE *f);
-
-/**
- * Write the raw data of the resource to the given file given by name.
- * The name is relative to the current working directory.
- * @return 0 on success
- */
-int resource_fwrite_file(const struct resource *r, const char *fname);
-
-/**
- * Treat the given resource as a tar archive. Extract
- * the archive to the current directory.
- */
-int resource_untar(const struct resource *res);
-
-/**
- * Treat the given resource as a tar archive. Remove
- * all files (related to the current directory) listed
- * in the tar archive.
- */
-int resource_rm_by_tar(const struct resource *res);
-
-/**
- * Register a resource in the global list of resources.
- * Not intended for direct use, please check the REGISTER_RESOURCE
- * macro.
- */
-void resource_register(struct resource *r);
-
-/**
- * Definition of a resource linked externally (by means of the used toolchain).
- * Only the base name of the resource is expected. The name refers to the
- * linked pointers beg_<name> and end_<name> provided externally.
- */
-#define REGISTER_LINKED_RESOURCE(n) \
-extern const char beg_ ##n;         \
-extern const char end_ ##n;         \
-REGISTER_RESOURCE(n, &beg_ ##n, &end_ ##n) \
-
-/**
- * Definition of a resource described by its name, and pointers begin, end.
- */
-#define REGISTER_RESOURCE(n, b, e) \
-static struct resource linkres_ ##n = {       \
-	.name = RTE_STR(n),     \
-	.begin = b,             \
-	.end = e,               \
-};                              \
-RTE_INIT(resinitfn_ ##n)	\
-{                               \
-	resource_register(&linkres_ ##n);  \
-}
-
-#endif
diff --git a/app/test/test_resource.c b/app/test/test_resource.c
deleted file mode 100644
index 05c27db203..0000000000
--- a/app/test/test_resource.c
+++ /dev/null
@@ -1,104 +0,0 @@
-/* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2016 RehiveTech. All rights reserved.
- */
-
-#include <stdio.h>
-#include <string.h>
-
-#include "test.h"
-#include "resource.h"
-
-const char test_resource_dpdk_blob[] = {
-	'\x44', '\x50', '\x44', '\x4b', '\x00'
-};
-
-REGISTER_RESOURCE(test_resource_dpdk,
-		test_resource_dpdk_blob, test_resource_dpdk_blob + 4);
-
-static int test_resource_dpdk(void)
-{
-	const struct resource *r;
-
-	r = resource_find("test_resource_dpdk");
-	TEST_ASSERT_NOT_NULL(r, "Could not find test_resource_dpdk");
-	TEST_ASSERT(!strcmp(r->name, "test_resource_dpdk"),
-			"Found resource %s, expected test_resource_dpdk",
-			r->name);
-
-	TEST_ASSERT(!strncmp("DPDK", r->begin, 4),
-			"Unexpected payload: %.4s...", r->begin);
-
-	return 0;
-}
-
-REGISTER_LINKED_RESOURCE(test_resource_c);
-
-static int test_resource_c(void)
-{
-	const struct resource *r;
-	FILE *f;
-
-	r = resource_find("test_resource_c");
-	TEST_ASSERT_NOT_NULL(r, "No test_resource_c found");
-	TEST_ASSERT(!strcmp(r->name, "test_resource_c"),
-			"Found resource %s, expected test_resource_c",
-			r->name);
-
-	TEST_ASSERT_SUCCESS(resource_fwrite_file(r, "test_resource.c"),
-			"Failed to write file %s", r->name);
-
-	f = fopen("test_resource.c", "r");
-	TEST_ASSERT_NOT_NULL(f,
-			"Missing extracted file resource.c");
-	fclose(f);
-	remove("test_resource.c");
-
-	return 0;
-}
-
-#ifdef RTE_APP_TEST_RESOURCE_TAR
-REGISTER_LINKED_RESOURCE(test_resource_tar);
-
-static int test_resource_tar(void)
-{
-	const struct resource *r;
-	FILE *f;
-
-	r = resource_find("test_resource_tar");
-	TEST_ASSERT_NOT_NULL(r, "No test_resource_tar found");
-	TEST_ASSERT(!strcmp(r->name, "test_resource_tar"),
-			"Found resource %s, expected test_resource_tar",
-			r->name);
-
-	TEST_ASSERT_SUCCESS(resource_untar(r),
-			"Failed to to untar %s", r->name);
-
-	f = fopen("test_resource.c", "r");
-	TEST_ASSERT_NOT_NULL(f,
-			"Missing extracted file test_resource.c");
-	fclose(f);
-
-	TEST_ASSERT_SUCCESS(resource_rm_by_tar(r),
-			"Failed to remove extracted contents of %s", r->name);
-	return 0;
-}
-
-#endif /* RTE_APP_TEST_RESOURCE_TAR */
-
-static int test_resource(void)
-{
-	if (test_resource_dpdk())
-		return -1;
-
-	if (test_resource_c())
-		return -1;
-
-#ifdef RTE_APP_TEST_RESOURCE_TAR
-	if (test_resource_tar())
-		return -1;
-#endif /* RTE_APP_TEST_RESOURCE_TAR */
-
-	return 0;
-}
-
-REGISTER_TEST_COMMAND(resource_autotest, test_resource);
-- 
2.43.0


^ permalink raw reply	[flat|nested] 34+ messages in thread

* [PATCH v4 3/3] test: restore cfgfile tests
  2024-08-01 17:29 ` [PATCH v4 0/3] restore lost " Stephen Hemminger
  2024-08-01 17:29   ` [PATCH v4 1/3] buildtools: add helper to convert text file to header Stephen Hemminger
  2024-08-01 17:29   ` [PATCH v4 2/3] test: remove unused resource API Stephen Hemminger
@ 2024-08-01 17:29   ` Stephen Hemminger
  2024-08-02 15:21     ` Bruce Richardson
  2 siblings, 1 reply; 34+ messages in thread
From: Stephen Hemminger @ 2024-08-01 17:29 UTC (permalink / raw)
  To: dev; +Cc: Stephen Hemminger

These tests were not built since the conversion to meson.
Instead of using embedded resource functions, put data in include
file and generate temporary file before the test.

Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
 app/meson.build                    |   3 +-
 app/test/meson.build               |   6 +-
 app/test/test_cfgfile.c            | 153 +++++++++++++++++++----------
 app/test/test_cfgfiles/meson.build |  19 ++++
 4 files changed, 129 insertions(+), 52 deletions(-)
 create mode 100644 app/test/test_cfgfiles/meson.build

diff --git a/app/meson.build b/app/meson.build
index 5b2c80c7a1..e2db888ae1 100644
--- a/app/meson.build
+++ b/app/meson.build
@@ -55,6 +55,7 @@ foreach app:apps
     build = true
     reason = '<unknown reason>' # set if build == false to explain
     sources = []
+    resources = []
     includes = []
     cflags = default_cflags
     ldflags = default_ldflags
@@ -115,7 +116,7 @@ foreach app:apps
     endif
 
     exec = executable('dpdk-' + name,
-            sources,
+            [ sources, resources ],
             c_args: cflags,
             link_args: ldflags,
             link_whole: link_libs,
diff --git a/app/test/meson.build b/app/test/meson.build
index 62478c0bb6..b2bb7c36f6 100644
--- a/app/test/meson.build
+++ b/app/test/meson.build
@@ -35,7 +35,7 @@ source_file_deps = {
     'test_bitratestats.c': ['metrics', 'bitratestats', 'ethdev'] + sample_packet_forward_deps,
     'test_bpf.c': ['bpf', 'net'],
     'test_byteorder.c': [],
-#    'test_cfgfile.c': ['cfgfile'],
+    'test_cfgfile.c': ['cfgfile'],
     'test_cksum.c': ['net'],
     'test_cksum_perf.c': ['net'],
     'test_cmdline.c': [],
@@ -261,3 +261,7 @@ if not is_windows
             build_by_default: true,
             install: false)
 endif
+
+subdir('test_cfgfiles')
+
+resources += test_cfgfile_h
diff --git a/app/test/test_cfgfile.c b/app/test/test_cfgfile.c
index a5e3d8699c..7cfcaf348a 100644
--- a/app/test/test_cfgfile.c
+++ b/app/test/test_cfgfile.c
@@ -5,48 +5,54 @@
 #include <stdio.h>
 #include <string.h>
 #include <stdint.h>
-#include <sys/queue.h>
+#include <unistd.h>
+
+#ifdef RTE_EXEC_ENV_WINDOWS
+#include <io.h>
+#endif
 
 #include <rte_cfgfile.h>
 
 #include "test.h"
-#include "resource.h"
-
-
-#define CFG_FILES_ETC "test_cfgfiles/etc"
 
-REGISTER_LINKED_RESOURCE(test_cfgfiles);
+#include "test_cfgfiles.h"
 
 static int
-test_cfgfile_setup(void)
+make_tmp_file(char *filename, const char *prefix, const char *data)
 {
-	const struct resource *r;
-	int ret;
+	size_t len = strlen(data);
+	size_t count;
+	FILE *f;
 
-	r = resource_find("test_cfgfiles");
-	TEST_ASSERT_NOT_NULL(r, "missing resource test_cfgfiles");
+#ifdef RTE_EXEC_ENV_WINDOWS
+	char tempDirName[MAX_PATH - 14];
 
-	ret = resource_untar(r);
-	TEST_ASSERT_SUCCESS(ret, "failed to untar %s", r->name);
+	if (GetTempPathA(sizeof(tempDirName), tempDirName) == 0)
+		return -1;
 
-	return 0;
-}
+	if (GetTempFileNameA(tempDirName, prefix, 0, filename) == 0)
+		return -1;
 
-static int
-test_cfgfile_cleanup(void)
-{
-	const struct resource *r;
-	int ret;
+	f = fopen(filename, "wt");
+#else
+	snprintf(filename, PATH_MAX, "/tmp/%s_XXXXXXX", prefix);
 
-	r = resource_find("test_cfgfiles");
-	TEST_ASSERT_NOT_NULL(r, "missing resource test_cfgfiles");
+	int fd = mkstemp(filename);
+	if (fd < 0)
+		return -1;
 
-	ret = resource_rm_by_tar(r);
-	TEST_ASSERT_SUCCESS(ret, "Failed to delete resource %s", r->name);
+	f = fdopen(fd, "w");
+#endif
+	if (f == NULL)
+		return -1;
 
-	return 0;
+	count = fwrite(data, sizeof(char), len, f);
+	fclose(f);
+
+	return (count == len) ? 0 : -1;
 }
 
+
 static int
 _test_cfgfile_sample(struct rte_cfgfile *cfgfile)
 {
@@ -87,9 +93,13 @@ static int
 test_cfgfile_sample1(void)
 {
 	struct rte_cfgfile *cfgfile;
+	char filename[PATH_MAX];
 	int ret;
 
-	cfgfile = rte_cfgfile_load(CFG_FILES_ETC "/sample1.ini", 0);
+	ret = make_tmp_file(filename, "sample1", sample1_ini);
+	TEST_ASSERT_SUCCESS(ret, "Failed to setup temp file");
+
+	cfgfile = rte_cfgfile_load(filename, 0);
 	TEST_ASSERT_NOT_NULL(cfgfile, "Failed to load config file");
 
 	ret = _test_cfgfile_sample(cfgfile);
@@ -98,6 +108,8 @@ test_cfgfile_sample1(void)
 	ret = rte_cfgfile_close(cfgfile);
 	TEST_ASSERT_SUCCESS(ret, "Failed to close cfgfile");
 
+	remove(filename);
+
 	return 0;
 }
 
@@ -106,15 +118,18 @@ test_cfgfile_sample2(void)
 {
 	struct rte_cfgfile_parameters params;
 	struct rte_cfgfile *cfgfile;
+	char filename[PATH_MAX];
 	int ret;
 
+	ret = make_tmp_file(filename, "sample2", sample2_ini);
+	TEST_ASSERT_SUCCESS(ret, "Failed to setup temp file");
+
 	/* override comment character */
 	memset(&params, 0, sizeof(params));
 	params.comment_character = '#';
 
-	cfgfile = rte_cfgfile_load_with_params(CFG_FILES_ETC "/sample2.ini", 0,
-					       &params);
-	TEST_ASSERT_NOT_NULL(cfgfile, "Failed to parse sample2.ini");
+	cfgfile = rte_cfgfile_load_with_params(filename, 0, &params);
+	TEST_ASSERT_NOT_NULL(cfgfile, "Failed to parse sample2");
 
 	ret = _test_cfgfile_sample(cfgfile);
 	TEST_ASSERT_SUCCESS(ret, "Failed to validate sample file: %d", ret);
@@ -122,6 +137,8 @@ test_cfgfile_sample2(void)
 	ret = rte_cfgfile_close(cfgfile);
 	TEST_ASSERT_SUCCESS(ret, "Failed to close cfgfile");
 
+	remove(filename);
+
 	return 0;
 }
 
@@ -129,10 +146,14 @@ static int
 test_cfgfile_realloc_sections(void)
 {
 	struct rte_cfgfile *cfgfile;
+	char filename[PATH_MAX];
 	int ret;
 	const char *value;
 
-	cfgfile = rte_cfgfile_load(CFG_FILES_ETC "/realloc_sections.ini", 0);
+	ret = make_tmp_file(filename, "realloc", realloc_sections_ini);
+	TEST_ASSERT_SUCCESS(ret, "Failed to setup temp file");
+
+	cfgfile = rte_cfgfile_load(filename, 0);
 	TEST_ASSERT_NOT_NULL(cfgfile, "Failed to load config file");
 
 	ret = rte_cfgfile_num_sections(cfgfile, NULL, 0);
@@ -152,13 +173,15 @@ test_cfgfile_realloc_sections(void)
 	TEST_ASSERT(strcmp("value8_section9", value) == 0,
 		    "key unexpected value: %s", value);
 
-	ret = rte_cfgfile_save(cfgfile, "/tmp/cfgfile_save.ini");
+	ret = rte_cfgfile_save(cfgfile, "/tmp/cfg_save.ini");
 	TEST_ASSERT_SUCCESS(ret, "Failed to save *.ini file");
-	remove("/tmp/cfgfile_save.ini");
+	remove("/tmp/cfg_save.ini");
 
 	ret = rte_cfgfile_close(cfgfile);
 	TEST_ASSERT_SUCCESS(ret, "Failed to close cfgfile");
 
+	remove(filename);
+
 	return 0;
 }
 
@@ -166,10 +189,16 @@ static int
 test_cfgfile_invalid_section_header(void)
 {
 	struct rte_cfgfile *cfgfile;
+	char filename[PATH_MAX];
+	int ret;
+
+	ret = make_tmp_file(filename, "invalid", invalid_section_ini);
+	TEST_ASSERT_SUCCESS(ret, "Failed to setup temp file");
 
-	cfgfile = rte_cfgfile_load(CFG_FILES_ETC "/invalid_section.ini", 0);
+	cfgfile = rte_cfgfile_load(filename, 0);
 	TEST_ASSERT_NULL(cfgfile, "Expected failure did not occur");
 
+	remove(filename);
 	return 0;
 }
 
@@ -178,15 +207,20 @@ test_cfgfile_invalid_comment(void)
 {
 	struct rte_cfgfile_parameters params;
 	struct rte_cfgfile *cfgfile;
+	char filename[PATH_MAX];
+	int ret;
 
 	/* override comment character with an invalid one */
 	memset(&params, 0, sizeof(params));
 	params.comment_character = '$';
 
-	cfgfile = rte_cfgfile_load_with_params(CFG_FILES_ETC "/sample2.ini", 0,
-					       &params);
+	ret = make_tmp_file(filename, "sample2", sample2_ini);
+	TEST_ASSERT_SUCCESS(ret, "Failed to setup temp file");
+
+	cfgfile = rte_cfgfile_load_with_params(filename, 0, &params);
 	TEST_ASSERT_NULL(cfgfile, "Expected failure did not occur");
 
+	remove(filename);
 	return 0;
 }
 
@@ -194,10 +228,16 @@ static int
 test_cfgfile_invalid_key_value_pair(void)
 {
 	struct rte_cfgfile *cfgfile;
+	char filename[PATH_MAX];
+	int ret;
+
+	ret = make_tmp_file(filename, "empty_key", empty_key_value_ini);
+	TEST_ASSERT_SUCCESS(ret, "Failed to setup temp file");
 
-	cfgfile = rte_cfgfile_load(CFG_FILES_ETC "/empty_key_value.ini", 0);
+	cfgfile = rte_cfgfile_load(filename, 0);
 	TEST_ASSERT_NULL(cfgfile, "Expected failure did not occur");
 
+	remove(filename);
 	return 0;
 }
 
@@ -206,11 +246,14 @@ test_cfgfile_empty_key_value_pair(void)
 {
 	struct rte_cfgfile *cfgfile;
 	const char *value;
+	char filename[PATH_MAX];
 	int ret;
 
-	cfgfile = rte_cfgfile_load(CFG_FILES_ETC "/empty_key_value.ini",
-				   CFG_FLAG_EMPTY_VALUES);
-	TEST_ASSERT_NOT_NULL(cfgfile, "Failed to parse empty_key_value.ini");
+	ret = make_tmp_file(filename, "empty_key_value", empty_key_value_ini);
+	TEST_ASSERT_SUCCESS(ret, "Failed to setup temp file");
+
+	cfgfile = rte_cfgfile_load(filename, CFG_FLAG_EMPTY_VALUES);
+	TEST_ASSERT_NOT_NULL(cfgfile, "Failed to parse empty_key_value");
 
 	ret = rte_cfgfile_num_sections(cfgfile, NULL, 0);
 	TEST_ASSERT(ret == 1, "Unexpected number of sections: %d", ret);
@@ -227,6 +270,7 @@ test_cfgfile_empty_key_value_pair(void)
 	ret = rte_cfgfile_close(cfgfile);
 	TEST_ASSERT_SUCCESS(ret, "Failed to close cfgfile");
 
+	remove(filename);
 	return 0;
 }
 
@@ -234,10 +278,16 @@ static int
 test_cfgfile_missing_section(void)
 {
 	struct rte_cfgfile *cfgfile;
+	char filename[PATH_MAX];
+	int ret;
+
+	ret = make_tmp_file(filename, "missing_section", missing_section_ini);
+	TEST_ASSERT_SUCCESS(ret, "Failed to setup temp file");
 
-	cfgfile = rte_cfgfile_load(CFG_FILES_ETC "/missing_section.ini", 0);
+	cfgfile = rte_cfgfile_load(filename, 0);
 	TEST_ASSERT_NULL(cfgfile, "Expected failure did not occur");
 
+	remove(filename);
 	return 0;
 }
 
@@ -246,10 +296,13 @@ test_cfgfile_global_properties(void)
 {
 	struct rte_cfgfile *cfgfile;
 	const char *value;
+	char filename[PATH_MAX];
 	int ret;
 
-	cfgfile = rte_cfgfile_load(CFG_FILES_ETC "/missing_section.ini",
-				   CFG_FLAG_GLOBAL_SECTION);
+	ret = make_tmp_file(filename, "missing_section", missing_section_ini);
+	TEST_ASSERT_SUCCESS(ret, "Failed to setup temp file");
+
+	cfgfile = rte_cfgfile_load(filename, CFG_FLAG_GLOBAL_SECTION);
 	TEST_ASSERT_NOT_NULL(cfgfile, "Failed to load config file");
 
 	ret = rte_cfgfile_num_sections(cfgfile, NULL, 0);
@@ -268,6 +321,7 @@ test_cfgfile_global_properties(void)
 	ret = rte_cfgfile_close(cfgfile);
 	TEST_ASSERT_SUCCESS(ret, "Failed to close cfgfile");
 
+	remove(filename);
 	return 0;
 }
 
@@ -275,9 +329,13 @@ static int
 test_cfgfile_empty_file(void)
 {
 	struct rte_cfgfile *cfgfile;
+	char filename[PATH_MAX];
 	int ret;
 
-	cfgfile = rte_cfgfile_load(CFG_FILES_ETC "/empty.ini", 0);
+	ret = make_tmp_file(filename, "empty", empty_ini);
+	TEST_ASSERT_SUCCESS(ret, "Failed to setup temp file");
+
+	cfgfile = rte_cfgfile_load(filename, 0);
 	TEST_ASSERT_NOT_NULL(cfgfile, "Failed to load config file");
 
 	ret = rte_cfgfile_num_sections(cfgfile, NULL, 0);
@@ -286,15 +344,13 @@ test_cfgfile_empty_file(void)
 	ret = rte_cfgfile_close(cfgfile);
 	TEST_ASSERT_SUCCESS(ret, "Failed to close cfgfile");
 
+	remove(filename);
 	return 0;
 }
 
 static int
 test_cfgfile(void)
 {
-	if (test_cfgfile_setup())
-		return -1;
-
 	if (test_cfgfile_sample1())
 		return -1;
 
@@ -325,10 +381,7 @@ test_cfgfile(void)
 	if (test_cfgfile_empty_file())
 		return -1;
 
-	if (test_cfgfile_cleanup())
-		return -1;
-
 	return 0;
 }
 
-REGISTER_TEST_COMMAND(cfgfile_autotest, test_cfgfile);
+REGISTER_FAST_TEST(cfgfile_autotest, true, true, test_cfgfile);
diff --git a/app/test/test_cfgfiles/meson.build b/app/test/test_cfgfiles/meson.build
new file mode 100644
index 0000000000..068b61044a
--- /dev/null
+++ b/app/test/test_cfgfiles/meson.build
@@ -0,0 +1,19 @@
+# SPDX-License-Identifier: BSD-3-Clause
+
+test_cfgfiles = files(
+    'etc/empty.ini',
+    'etc/empty_key_value.ini',
+    'etc/invalid_section.ini',
+    'etc/line_too_long.ini',
+    'etc/missing_section.ini',
+    'etc/realloc_sections.ini',
+    'etc/sample1.ini',
+    'etc/sample2.ini',
+)
+
+# generate the header file used in cfgfile test
+test_cfgfile_h = custom_target('test_cfgfile',
+                          output: 'test_cfgfiles.h',
+                          input: test_cfgfiles,
+                          capture: true,
+                          command: [ header_gen_cmd, '@INPUT@'])
-- 
2.43.0


^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [PATCH v4 1/3] buildtools: add helper to convert text file to header
  2024-08-01 17:29   ` [PATCH v4 1/3] buildtools: add helper to convert text file to header Stephen Hemminger
@ 2024-08-02 15:15     ` Bruce Richardson
  0 siblings, 0 replies; 34+ messages in thread
From: Bruce Richardson @ 2024-08-02 15:15 UTC (permalink / raw)
  To: Stephen Hemminger; +Cc: dev

On Thu, Aug 01, 2024 at 10:29:08AM -0700, Stephen Hemminger wrote:
> Simple script to read a file and make it into a initialized
> C string in a header file.
> 
> Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
> ---
>  buildtools/gen-header.py | 36 ++++++++++++++++++++++++++++++++++++
>  buildtools/meson.build   |  2 +-
>  2 files changed, 37 insertions(+), 1 deletion(-)
>  create mode 100644 buildtools/gen-header.py
> 
Resulting header output LGTM

Acked-by: Bruce Richardson <bruce.richardson@intel.com>

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [PATCH v4 2/3] test: remove unused resource API
  2024-08-01 17:29   ` [PATCH v4 2/3] test: remove unused resource API Stephen Hemminger
@ 2024-08-02 15:16     ` Bruce Richardson
  0 siblings, 0 replies; 34+ messages in thread
From: Bruce Richardson @ 2024-08-02 15:16 UTC (permalink / raw)
  To: Stephen Hemminger; +Cc: dev

On Thu, Aug 01, 2024 at 10:29:09AM -0700, Stephen Hemminger wrote:
> This API was used only for cfgfile tests and was never built
> after the conversion to meson. Will be replaced by simpler
> method of doing cfgfile tests.
> 
> Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
> ---

It's always there in git history if we ever need it back again! :-)

Acked-by: Bruce Richardson <bruce.richardson@intel.com>

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [PATCH v4 3/3] test: restore cfgfile tests
  2024-08-01 17:29   ` [PATCH v4 3/3] test: restore cfgfile tests Stephen Hemminger
@ 2024-08-02 15:21     ` Bruce Richardson
  0 siblings, 0 replies; 34+ messages in thread
From: Bruce Richardson @ 2024-08-02 15:21 UTC (permalink / raw)
  To: Stephen Hemminger; +Cc: dev

On Thu, Aug 01, 2024 at 10:29:10AM -0700, Stephen Hemminger wrote:
> These tests were not built since the conversion to meson.
> Instead of using embedded resource functions, put data in include
> file and generate temporary file before the test.
> 
> Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
> ---
>  app/meson.build                    |   3 +-
>  app/test/meson.build               |   6 +-
>  app/test/test_cfgfile.c            | 153 +++++++++++++++++++----------
>  app/test/test_cfgfiles/meson.build |  19 ++++
>  4 files changed, 129 insertions(+), 52 deletions(-)
>  create mode 100644 app/test/test_cfgfiles/meson.build
> 

Tested-by: Bruce Richardson <bruce.richardson@intel.com>
Acked-by: Bruce Richardson <bruce.richardson@intel.com>

A further cleanup that could be done with the test files is to remove the
unnecessary "etc" subdirectory.

> diff --git a/app/meson.build b/app/meson.build
> index 5b2c80c7a1..e2db888ae1 100644
> --- a/app/meson.build
> +++ b/app/meson.build
> @@ -55,6 +55,7 @@ foreach app:apps
>      build = true
>      reason = '<unknown reason>' # set if build == false to explain
>      sources = []
> +    resources = []
>      includes = []
>      cflags = default_cflags
>      ldflags = default_ldflags
> @@ -115,7 +116,7 @@ foreach app:apps
>      endif
>  
>      exec = executable('dpdk-' + name,
> -            sources,
> +            [ sources, resources ],
>              c_args: cflags,
>              link_args: ldflags,
>              link_whole: link_libs,
> diff --git a/app/test/meson.build b/app/test/meson.build
> index 62478c0bb6..b2bb7c36f6 100644
> --- a/app/test/meson.build
> +++ b/app/test/meson.build
> @@ -35,7 +35,7 @@ source_file_deps = {
>      'test_bitratestats.c': ['metrics', 'bitratestats', 'ethdev'] + sample_packet_forward_deps,
>      'test_bpf.c': ['bpf', 'net'],
>      'test_byteorder.c': [],
> -#    'test_cfgfile.c': ['cfgfile'],
> +    'test_cfgfile.c': ['cfgfile'],
>      'test_cksum.c': ['net'],
>      'test_cksum_perf.c': ['net'],
>      'test_cmdline.c': [],
> @@ -261,3 +261,7 @@ if not is_windows
>              build_by_default: true,
>              install: false)
>  endif
> +
> +subdir('test_cfgfiles')
> +
> +resources += test_cfgfile_h
> diff --git a/app/test/test_cfgfile.c b/app/test/test_cfgfile.c
> index a5e3d8699c..7cfcaf348a 100644
> --- a/app/test/test_cfgfile.c
> +++ b/app/test/test_cfgfile.c
> @@ -5,48 +5,54 @@
>  #include <stdio.h>
>  #include <string.h>
>  #include <stdint.h>
> -#include <sys/queue.h>
> +#include <unistd.h>
> +
> +#ifdef RTE_EXEC_ENV_WINDOWS
> +#include <io.h>
> +#endif
>  
>  #include <rte_cfgfile.h>
>  
>  #include "test.h"
> -#include "resource.h"
> -
> -
> -#define CFG_FILES_ETC "test_cfgfiles/etc"
>  
> -REGISTER_LINKED_RESOURCE(test_cfgfiles);
> +#include "test_cfgfiles.h"
>  
>  static int
> -test_cfgfile_setup(void)
> +make_tmp_file(char *filename, const char *prefix, const char *data)
>  {
> -	const struct resource *r;
> -	int ret;
> +	size_t len = strlen(data);
> +	size_t count;
> +	FILE *f;
>  
> -	r = resource_find("test_cfgfiles");
> -	TEST_ASSERT_NOT_NULL(r, "missing resource test_cfgfiles");
> +#ifdef RTE_EXEC_ENV_WINDOWS
> +	char tempDirName[MAX_PATH - 14];
>  
> -	ret = resource_untar(r);
> -	TEST_ASSERT_SUCCESS(ret, "failed to untar %s", r->name);
> +	if (GetTempPathA(sizeof(tempDirName), tempDirName) == 0)
> +		return -1;
>  
> -	return 0;
> -}
> +	if (GetTempFileNameA(tempDirName, prefix, 0, filename) == 0)
> +		return -1;
>  
> -static int
> -test_cfgfile_cleanup(void)
> -{
> -	const struct resource *r;
> -	int ret;
> +	f = fopen(filename, "wt");
> +#else
> +	snprintf(filename, PATH_MAX, "/tmp/%s_XXXXXXX", prefix);
>  
> -	r = resource_find("test_cfgfiles");
> -	TEST_ASSERT_NOT_NULL(r, "missing resource test_cfgfiles");
> +	int fd = mkstemp(filename);
> +	if (fd < 0)
> +		return -1;
>  
> -	ret = resource_rm_by_tar(r);
> -	TEST_ASSERT_SUCCESS(ret, "Failed to delete resource %s", r->name);
> +	f = fdopen(fd, "w");
> +#endif
> +	if (f == NULL)
> +		return -1;
>  
> -	return 0;
> +	count = fwrite(data, sizeof(char), len, f);
> +	fclose(f);
> +
> +	return (count == len) ? 0 : -1;
>  }
>  
> +
>  static int
>  _test_cfgfile_sample(struct rte_cfgfile *cfgfile)
>  {
> @@ -87,9 +93,13 @@ static int
>  test_cfgfile_sample1(void)
>  {
>  	struct rte_cfgfile *cfgfile;
> +	char filename[PATH_MAX];
>  	int ret;
>  
> -	cfgfile = rte_cfgfile_load(CFG_FILES_ETC "/sample1.ini", 0);
> +	ret = make_tmp_file(filename, "sample1", sample1_ini);
> +	TEST_ASSERT_SUCCESS(ret, "Failed to setup temp file");
> +
> +	cfgfile = rte_cfgfile_load(filename, 0);
>  	TEST_ASSERT_NOT_NULL(cfgfile, "Failed to load config file");
>  
>  	ret = _test_cfgfile_sample(cfgfile);
> @@ -98,6 +108,8 @@ test_cfgfile_sample1(void)
>  	ret = rte_cfgfile_close(cfgfile);
>  	TEST_ASSERT_SUCCESS(ret, "Failed to close cfgfile");
>  
> +	remove(filename);
> +
>  	return 0;
>  }
>  
> @@ -106,15 +118,18 @@ test_cfgfile_sample2(void)
>  {
>  	struct rte_cfgfile_parameters params;
>  	struct rte_cfgfile *cfgfile;
> +	char filename[PATH_MAX];
>  	int ret;
>  
> +	ret = make_tmp_file(filename, "sample2", sample2_ini);
> +	TEST_ASSERT_SUCCESS(ret, "Failed to setup temp file");
> +
>  	/* override comment character */
>  	memset(&params, 0, sizeof(params));
>  	params.comment_character = '#';
>  
> -	cfgfile = rte_cfgfile_load_with_params(CFG_FILES_ETC "/sample2.ini", 0,
> -					       &params);
> -	TEST_ASSERT_NOT_NULL(cfgfile, "Failed to parse sample2.ini");
> +	cfgfile = rte_cfgfile_load_with_params(filename, 0, &params);
> +	TEST_ASSERT_NOT_NULL(cfgfile, "Failed to parse sample2");
>  
>  	ret = _test_cfgfile_sample(cfgfile);
>  	TEST_ASSERT_SUCCESS(ret, "Failed to validate sample file: %d", ret);
> @@ -122,6 +137,8 @@ test_cfgfile_sample2(void)
>  	ret = rte_cfgfile_close(cfgfile);
>  	TEST_ASSERT_SUCCESS(ret, "Failed to close cfgfile");
>  
> +	remove(filename);
> +
>  	return 0;
>  }
>  
> @@ -129,10 +146,14 @@ static int
>  test_cfgfile_realloc_sections(void)
>  {
>  	struct rte_cfgfile *cfgfile;
> +	char filename[PATH_MAX];
>  	int ret;
>  	const char *value;
>  
> -	cfgfile = rte_cfgfile_load(CFG_FILES_ETC "/realloc_sections.ini", 0);
> +	ret = make_tmp_file(filename, "realloc", realloc_sections_ini);
> +	TEST_ASSERT_SUCCESS(ret, "Failed to setup temp file");
> +
> +	cfgfile = rte_cfgfile_load(filename, 0);
>  	TEST_ASSERT_NOT_NULL(cfgfile, "Failed to load config file");
>  
>  	ret = rte_cfgfile_num_sections(cfgfile, NULL, 0);
> @@ -152,13 +173,15 @@ test_cfgfile_realloc_sections(void)
>  	TEST_ASSERT(strcmp("value8_section9", value) == 0,
>  		    "key unexpected value: %s", value);
>  
> -	ret = rte_cfgfile_save(cfgfile, "/tmp/cfgfile_save.ini");
> +	ret = rte_cfgfile_save(cfgfile, "/tmp/cfg_save.ini");
>  	TEST_ASSERT_SUCCESS(ret, "Failed to save *.ini file");
> -	remove("/tmp/cfgfile_save.ini");
> +	remove("/tmp/cfg_save.ini");
>  
>  	ret = rte_cfgfile_close(cfgfile);
>  	TEST_ASSERT_SUCCESS(ret, "Failed to close cfgfile");
>  
> +	remove(filename);
> +
>  	return 0;
>  }
>  
> @@ -166,10 +189,16 @@ static int
>  test_cfgfile_invalid_section_header(void)
>  {
>  	struct rte_cfgfile *cfgfile;
> +	char filename[PATH_MAX];
> +	int ret;
> +
> +	ret = make_tmp_file(filename, "invalid", invalid_section_ini);
> +	TEST_ASSERT_SUCCESS(ret, "Failed to setup temp file");
>  
> -	cfgfile = rte_cfgfile_load(CFG_FILES_ETC "/invalid_section.ini", 0);
> +	cfgfile = rte_cfgfile_load(filename, 0);
>  	TEST_ASSERT_NULL(cfgfile, "Expected failure did not occur");
>  
> +	remove(filename);
>  	return 0;
>  }
>  
> @@ -178,15 +207,20 @@ test_cfgfile_invalid_comment(void)
>  {
>  	struct rte_cfgfile_parameters params;
>  	struct rte_cfgfile *cfgfile;
> +	char filename[PATH_MAX];
> +	int ret;
>  
>  	/* override comment character with an invalid one */
>  	memset(&params, 0, sizeof(params));
>  	params.comment_character = '$';
>  
> -	cfgfile = rte_cfgfile_load_with_params(CFG_FILES_ETC "/sample2.ini", 0,
> -					       &params);
> +	ret = make_tmp_file(filename, "sample2", sample2_ini);
> +	TEST_ASSERT_SUCCESS(ret, "Failed to setup temp file");
> +
> +	cfgfile = rte_cfgfile_load_with_params(filename, 0, &params);
>  	TEST_ASSERT_NULL(cfgfile, "Expected failure did not occur");
>  
> +	remove(filename);
>  	return 0;
>  }
>  
> @@ -194,10 +228,16 @@ static int
>  test_cfgfile_invalid_key_value_pair(void)
>  {
>  	struct rte_cfgfile *cfgfile;
> +	char filename[PATH_MAX];
> +	int ret;
> +
> +	ret = make_tmp_file(filename, "empty_key", empty_key_value_ini);
> +	TEST_ASSERT_SUCCESS(ret, "Failed to setup temp file");
>  
> -	cfgfile = rte_cfgfile_load(CFG_FILES_ETC "/empty_key_value.ini", 0);
> +	cfgfile = rte_cfgfile_load(filename, 0);
>  	TEST_ASSERT_NULL(cfgfile, "Expected failure did not occur");
>  
> +	remove(filename);
>  	return 0;
>  }
>  
> @@ -206,11 +246,14 @@ test_cfgfile_empty_key_value_pair(void)
>  {
>  	struct rte_cfgfile *cfgfile;
>  	const char *value;
> +	char filename[PATH_MAX];
>  	int ret;
>  
> -	cfgfile = rte_cfgfile_load(CFG_FILES_ETC "/empty_key_value.ini",
> -				   CFG_FLAG_EMPTY_VALUES);
> -	TEST_ASSERT_NOT_NULL(cfgfile, "Failed to parse empty_key_value.ini");
> +	ret = make_tmp_file(filename, "empty_key_value", empty_key_value_ini);
> +	TEST_ASSERT_SUCCESS(ret, "Failed to setup temp file");
> +
> +	cfgfile = rte_cfgfile_load(filename, CFG_FLAG_EMPTY_VALUES);
> +	TEST_ASSERT_NOT_NULL(cfgfile, "Failed to parse empty_key_value");
>  
>  	ret = rte_cfgfile_num_sections(cfgfile, NULL, 0);
>  	TEST_ASSERT(ret == 1, "Unexpected number of sections: %d", ret);
> @@ -227,6 +270,7 @@ test_cfgfile_empty_key_value_pair(void)
>  	ret = rte_cfgfile_close(cfgfile);
>  	TEST_ASSERT_SUCCESS(ret, "Failed to close cfgfile");
>  
> +	remove(filename);
>  	return 0;
>  }
>  
> @@ -234,10 +278,16 @@ static int
>  test_cfgfile_missing_section(void)
>  {
>  	struct rte_cfgfile *cfgfile;
> +	char filename[PATH_MAX];
> +	int ret;
> +
> +	ret = make_tmp_file(filename, "missing_section", missing_section_ini);
> +	TEST_ASSERT_SUCCESS(ret, "Failed to setup temp file");
>  
> -	cfgfile = rte_cfgfile_load(CFG_FILES_ETC "/missing_section.ini", 0);
> +	cfgfile = rte_cfgfile_load(filename, 0);
>  	TEST_ASSERT_NULL(cfgfile, "Expected failure did not occur");
>  
> +	remove(filename);
>  	return 0;
>  }
>  
> @@ -246,10 +296,13 @@ test_cfgfile_global_properties(void)
>  {
>  	struct rte_cfgfile *cfgfile;
>  	const char *value;
> +	char filename[PATH_MAX];
>  	int ret;
>  
> -	cfgfile = rte_cfgfile_load(CFG_FILES_ETC "/missing_section.ini",
> -				   CFG_FLAG_GLOBAL_SECTION);
> +	ret = make_tmp_file(filename, "missing_section", missing_section_ini);
> +	TEST_ASSERT_SUCCESS(ret, "Failed to setup temp file");
> +
> +	cfgfile = rte_cfgfile_load(filename, CFG_FLAG_GLOBAL_SECTION);
>  	TEST_ASSERT_NOT_NULL(cfgfile, "Failed to load config file");
>  
>  	ret = rte_cfgfile_num_sections(cfgfile, NULL, 0);
> @@ -268,6 +321,7 @@ test_cfgfile_global_properties(void)
>  	ret = rte_cfgfile_close(cfgfile);
>  	TEST_ASSERT_SUCCESS(ret, "Failed to close cfgfile");
>  
> +	remove(filename);
>  	return 0;
>  }
>  
> @@ -275,9 +329,13 @@ static int
>  test_cfgfile_empty_file(void)
>  {
>  	struct rte_cfgfile *cfgfile;
> +	char filename[PATH_MAX];
>  	int ret;
>  
> -	cfgfile = rte_cfgfile_load(CFG_FILES_ETC "/empty.ini", 0);
> +	ret = make_tmp_file(filename, "empty", empty_ini);
> +	TEST_ASSERT_SUCCESS(ret, "Failed to setup temp file");
> +
> +	cfgfile = rte_cfgfile_load(filename, 0);
>  	TEST_ASSERT_NOT_NULL(cfgfile, "Failed to load config file");
>  
>  	ret = rte_cfgfile_num_sections(cfgfile, NULL, 0);
> @@ -286,15 +344,13 @@ test_cfgfile_empty_file(void)
>  	ret = rte_cfgfile_close(cfgfile);
>  	TEST_ASSERT_SUCCESS(ret, "Failed to close cfgfile");
>  
> +	remove(filename);
>  	return 0;
>  }
>  
>  static int
>  test_cfgfile(void)
>  {
> -	if (test_cfgfile_setup())
> -		return -1;
> -
>  	if (test_cfgfile_sample1())
>  		return -1;
>  
> @@ -325,10 +381,7 @@ test_cfgfile(void)
>  	if (test_cfgfile_empty_file())
>  		return -1;
>  
> -	if (test_cfgfile_cleanup())
> -		return -1;
> -
>  	return 0;
>  }
>  
> -REGISTER_TEST_COMMAND(cfgfile_autotest, test_cfgfile);
> +REGISTER_FAST_TEST(cfgfile_autotest, true, true, test_cfgfile);
> diff --git a/app/test/test_cfgfiles/meson.build b/app/test/test_cfgfiles/meson.build
> new file mode 100644
> index 0000000000..068b61044a
> --- /dev/null
> +++ b/app/test/test_cfgfiles/meson.build
> @@ -0,0 +1,19 @@
> +# SPDX-License-Identifier: BSD-3-Clause
> +
> +test_cfgfiles = files(
> +    'etc/empty.ini',
> +    'etc/empty_key_value.ini',
> +    'etc/invalid_section.ini',
> +    'etc/line_too_long.ini',
> +    'etc/missing_section.ini',
> +    'etc/realloc_sections.ini',
> +    'etc/sample1.ini',
> +    'etc/sample2.ini',
> +)
> +
> +# generate the header file used in cfgfile test
> +test_cfgfile_h = custom_target('test_cfgfile',
> +                          output: 'test_cfgfiles.h',
> +                          input: test_cfgfiles,
> +                          capture: true,
> +                          command: [ header_gen_cmd, '@INPUT@'])
> -- 
> 2.43.0
> 

^ permalink raw reply	[flat|nested] 34+ messages in thread

* [PATCH v5 0/4] restore unused cfgfile tests
  2024-07-30 22:51 [PATCH 0/3] restore cfgfile library tests Stephen Hemminger
                   ` (5 preceding siblings ...)
  2024-08-01 17:29 ` [PATCH v4 0/3] restore lost " Stephen Hemminger
@ 2024-08-02 16:44 ` Stephen Hemminger
  2024-08-02 16:45   ` [PATCH v5 1/4] buildtools: add helper to convert text file to header Stephen Hemminger
                     ` (3 more replies)
  2024-08-13 15:57 ` [PATCH v6 0/4] test: restore cfgfile lib tests Stephen Hemminger
  7 siblings, 4 replies; 34+ messages in thread
From: Stephen Hemminger @ 2024-08-02 16:44 UTC (permalink / raw)
  To: dev; +Cc: Stephen Hemminger

The cfgfile tests did not get built since conversion to meson
and they used an awkward way to manage the test data.

This patchset converts the tests to use a helper to take
text file and make it into a C header. Then use the C header
to generate temporary files as needed.

v5 - rearrange tests input files
   - use unit_suite_runner
   - more Windows fixes

Stephen Hemminger (4):
  buildtools: add helper to convert text file to header
  test: remove unused resource API
  test: restore cfgfile tests
  test: rearrange test_cfgfiles cases

 app/meson.build                               |   3 +-
 app/test/meson.build                          |   8 +-
 app/test/resource.c                           | 276 ------------------
 app/test/resource.h                           | 106 -------
 app/test/test_cfgfile.c                       | 213 ++++++++------
 app/test/test_cfgfiles/{etc => }/empty.ini    |   0
 .../{etc => }/empty_key_value.ini             |   0
 .../{etc => }/invalid_section.ini             |   0
 .../test_cfgfiles/{etc => }/line_too_long.ini |   0
 app/test/test_cfgfiles/meson.build            |  19 ++
 .../{etc => }/missing_section.ini             |   0
 .../{etc => }/realloc_sections.ini            |   0
 app/test/test_cfgfiles/{etc => }/sample1.ini  |   0
 app/test/test_cfgfiles/{etc => }/sample2.ini  |   0
 app/test/test_resource.c                      | 104 -------
 buildtools/gen-header.py                      |  36 +++
 buildtools/meson.build                        |   2 +-
 17 files changed, 194 insertions(+), 573 deletions(-)
 delete mode 100644 app/test/resource.c
 delete mode 100644 app/test/resource.h
 rename app/test/test_cfgfiles/{etc => }/empty.ini (100%)
 rename app/test/test_cfgfiles/{etc => }/empty_key_value.ini (100%)
 rename app/test/test_cfgfiles/{etc => }/invalid_section.ini (100%)
 rename app/test/test_cfgfiles/{etc => }/line_too_long.ini (100%)
 create mode 100644 app/test/test_cfgfiles/meson.build
 rename app/test/test_cfgfiles/{etc => }/missing_section.ini (100%)
 rename app/test/test_cfgfiles/{etc => }/realloc_sections.ini (100%)
 rename app/test/test_cfgfiles/{etc => }/sample1.ini (100%)
 rename app/test/test_cfgfiles/{etc => }/sample2.ini (100%)
 delete mode 100644 app/test/test_resource.c
 create mode 100644 buildtools/gen-header.py

-- 
2.43.0


^ permalink raw reply	[flat|nested] 34+ messages in thread

* [PATCH v5 1/4] buildtools: add helper to convert text file to header
  2024-08-02 16:44 ` [PATCH v5 0/4] restore unused " Stephen Hemminger
@ 2024-08-02 16:45   ` Stephen Hemminger
  2024-08-02 16:45   ` [PATCH v5 2/4] test: remove unused resource API Stephen Hemminger
                     ` (2 subsequent siblings)
  3 siblings, 0 replies; 34+ messages in thread
From: Stephen Hemminger @ 2024-08-02 16:45 UTC (permalink / raw)
  To: dev; +Cc: Stephen Hemminger, Bruce Richardson

Simple script to read a file and make it into a initialized
C string in a header file.

Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
Acked-by: Bruce Richardson <bruce.richardson@intel.com>
---
 buildtools/gen-header.py | 36 ++++++++++++++++++++++++++++++++++++
 buildtools/meson.build   |  2 +-
 2 files changed, 37 insertions(+), 1 deletion(-)
 create mode 100644 buildtools/gen-header.py

diff --git a/buildtools/gen-header.py b/buildtools/gen-header.py
new file mode 100644
index 0000000000..06e645863c
--- /dev/null
+++ b/buildtools/gen-header.py
@@ -0,0 +1,36 @@
+#! /usr/bin/env python3
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright (c) 2023 Stephen Hemminger <stephen@networkplumber.org>
+
+"""
+Script to read a text file and convert it into a header file.
+"""
+import sys
+import os
+
+
+def main():
+    '''program main function'''
+    print(f'/* File autogenerated by {sys.argv[0]} */')
+    for path in sys.argv[1:]:
+        name = os.path.basename(path)
+        print()
+        print(f'/* generated from {name} */')
+        with open(path, "r") as f:
+            array = name.replace(".", "_")
+            print(f'static const char {array}[] = ' + '{')
+            line = f.readline()
+
+            # make sure empty string is null terminated
+            if not line:
+                print('    ""')
+
+            while line:
+                s = repr(line)
+                print('    {}'.format(s.replace("'", '"')))
+                line = f.readline()
+            print('};')
+
+
+if __name__ == "__main__":
+    main()
diff --git a/buildtools/meson.build b/buildtools/meson.build
index 3adf34e1a8..bc818a71d5 100644
--- a/buildtools/meson.build
+++ b/buildtools/meson.build
@@ -24,6 +24,7 @@ get_numa_count_cmd = py3 + files('get-numa-count.py')
 get_test_suites_cmd = py3 + files('get-test-suites.py')
 has_hugepages_cmd = py3 + files('has-hugepages.py')
 cmdline_gen_cmd = py3 + files('dpdk-cmdline-gen.py')
+header_gen_cmd = py3 + files('gen-header.py')
 
 # install any build tools that end-users might want also
 install_data([
@@ -48,4 +49,3 @@ else
     pmdinfo += 'ar'
     pmdinfogen += 'elf'
 endif
-
-- 
2.43.0


^ permalink raw reply	[flat|nested] 34+ messages in thread

* [PATCH v5 2/4] test: remove unused resource API
  2024-08-02 16:44 ` [PATCH v5 0/4] restore unused " Stephen Hemminger
  2024-08-02 16:45   ` [PATCH v5 1/4] buildtools: add helper to convert text file to header Stephen Hemminger
@ 2024-08-02 16:45   ` Stephen Hemminger
  2024-08-02 16:45   ` [PATCH v5 3/4] test: restore cfgfile tests Stephen Hemminger
  2024-08-02 16:45   ` [PATCH v5 4/4] test: rearrange test_cfgfiles cases Stephen Hemminger
  3 siblings, 0 replies; 34+ messages in thread
From: Stephen Hemminger @ 2024-08-02 16:45 UTC (permalink / raw)
  To: dev; +Cc: Stephen Hemminger, Bruce Richardson

This API was used only for cfgfile tests and was never built
after the conversion to meson. Will be replaced by simpler
method of doing cfgfile tests.

Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
Acked-by: Bruce Richardson <bruce.richardson@intel.com>
---
 app/test/meson.build     |   2 -
 app/test/resource.c      | 276 ---------------------------------------
 app/test/resource.h      | 106 ---------------
 app/test/test_resource.c | 104 ---------------
 4 files changed, 488 deletions(-)
 delete mode 100644 app/test/resource.c
 delete mode 100644 app/test/resource.h
 delete mode 100644 app/test/test_resource.c

diff --git a/app/test/meson.build b/app/test/meson.build
index e29258e6ec..62478c0bb6 100644
--- a/app/test/meson.build
+++ b/app/test/meson.build
@@ -20,7 +20,6 @@ test_cryptodev_deps = ['bus_vdev', 'net', 'cryptodev', 'security']
 source_file_deps = {
     # The C files providing functionality to other test cases
     'packet_burst_generator.c': packet_burst_generator_deps,
-#    'resource.c': [],          # unused currently.
     'sample_packet_forward.c': sample_packet_forward_deps,
     'virtual_pmd.c': virtual_pmd_deps,
 
@@ -154,7 +153,6 @@ source_file_deps = {
     'test_reciprocal_division_perf.c': [],
     'test_red.c': ['sched'],
     'test_reorder.c': ['reorder'],
-#    'test_resource.c': [],
     'test_rib.c': ['net', 'rib'],
     'test_rib6.c': ['net', 'rib'],
     'test_ring.c': ['ptr_compress'],
diff --git a/app/test/resource.c b/app/test/resource.c
deleted file mode 100644
index 34465f1668..0000000000
--- a/app/test/resource.c
+++ /dev/null
@@ -1,276 +0,0 @@
-/* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2016 RehiveTech. All rights reserved.
- */
-
-#include <stdio.h>
-#include <string.h>
-#include <errno.h>
-#include <sys/queue.h>
-
-#include <rte_debug.h>
-
-#include "resource.h"
-
-struct resource_list resource_list = TAILQ_HEAD_INITIALIZER(resource_list);
-
-size_t resource_size(const struct resource *r)
-{
-	return r->end - r->begin;
-}
-
-const struct resource *resource_find(const char *name)
-{
-	struct resource *r;
-
-	TAILQ_FOREACH(r, &resource_list, next) {
-		RTE_VERIFY(r->name);
-
-		if (!strcmp(r->name, name))
-			return r;
-	}
-
-	return NULL;
-}
-
-int resource_fwrite(const struct resource *r, FILE *f)
-{
-	const size_t goal = resource_size(r);
-	size_t total = 0;
-
-	while (total < goal) {
-		size_t wlen = fwrite(r->begin + total, 1, goal - total, f);
-		if (wlen == 0) {
-			perror(__func__);
-			return -1;
-		}
-
-		total += wlen;
-	}
-
-	return 0;
-}
-
-int resource_fwrite_file(const struct resource *r, const char *fname)
-{
-	FILE *f;
-	int ret;
-
-	f = fopen(fname, "w");
-	if (f == NULL) {
-		perror(__func__);
-		return -1;
-	}
-
-	ret = resource_fwrite(r, f);
-	fclose(f);
-	return ret;
-}
-
-#ifdef RTE_APP_TEST_RESOURCE_TAR
-#include <archive.h>
-#include <archive_entry.h>
-
-static int do_copy(struct archive *r, struct archive *w)
-{
-	const void *buf;
-	size_t len;
-#if ARCHIVE_VERSION_NUMBER >= 3000000
-	int64_t off;
-#else
-	off_t off;
-#endif
-	int ret;
-
-	while (1) {
-		ret = archive_read_data_block(r, &buf, &len, &off);
-		if (ret == ARCHIVE_RETRY)
-			continue;
-
-		if (ret == ARCHIVE_EOF)
-			return 0;
-
-		if (ret != ARCHIVE_OK)
-			return ret;
-
-		do {
-			ret = archive_write_data_block(w, buf, len, off);
-			if (ret != ARCHIVE_OK && ret != ARCHIVE_RETRY)
-				return ret;
-		} while (ret != ARCHIVE_OK);
-	}
-}
-
-int resource_untar(const struct resource *res)
-{
-	struct archive *r;
-	struct archive *w;
-	struct archive_entry *e;
-	void *p;
-	int flags = 0;
-	int ret;
-
-	p = malloc(resource_size(res));
-	if (p == NULL)
-		rte_panic("Failed to malloc %zu B\n", resource_size(res));
-
-	memcpy(p, res->begin, resource_size(res));
-
-	r = archive_read_new();
-	if (r == NULL) {
-		free(p);
-		return -1;
-	}
-
-	archive_read_support_format_all(r);
-	archive_read_support_filter_all(r);
-
-	w = archive_write_disk_new();
-	if (w == NULL) {
-		archive_read_free(r);
-		free(p);
-		return -1;
-	}
-
-	flags |= ARCHIVE_EXTRACT_PERM;
-	flags |= ARCHIVE_EXTRACT_FFLAGS;
-	archive_write_disk_set_options(w, flags);
-	archive_write_disk_set_standard_lookup(w);
-
-	ret = archive_read_open_memory(r, p, resource_size(res));
-	if (ret != ARCHIVE_OK)
-		goto fail;
-
-	while (1) {
-		ret = archive_read_next_header(r, &e);
-		if (ret == ARCHIVE_EOF)
-			break;
-		if (ret != ARCHIVE_OK)
-			goto fail;
-
-		ret = archive_write_header(w, e);
-		if (ret == ARCHIVE_EOF)
-			break;
-		if (ret != ARCHIVE_OK)
-			goto fail;
-
-		if (archive_entry_size(e) == 0)
-			continue;
-
-		ret = do_copy(r, w);
-		if (ret != ARCHIVE_OK)
-			goto fail;
-
-		ret = archive_write_finish_entry(w);
-		if (ret != ARCHIVE_OK)
-			goto fail;
-	}
-
-	archive_write_free(w);
-	archive_read_free(r);
-	free(p);
-	return 0;
-
-fail:
-	archive_write_free(w);
-	archive_read_free(r);
-	free(p);
-	rte_panic("Failed: %s\n", archive_error_string(r));
-	return -1;
-}
-
-int resource_rm_by_tar(const struct resource *res)
-{
-	struct archive *r;
-	struct archive_entry *e;
-	void *p;
-	int try_again = 1;
-	int attempts = 0;
-	int ret;
-
-	p = malloc(resource_size(res));
-	if (p == NULL)
-		rte_panic("Failed to malloc %zu B\n", resource_size(res));
-
-	memcpy(p, res->begin, resource_size(res));
-
-	/*
-	 * If somebody creates a file somewhere inside the extracted TAR
-	 * hierarchy during a test the resource_rm_by_tar might loop
-	 * infinitely. We prevent this by adding the attempts counter there.
-	 * In normal case, max N iteration is done where N is the depth of
-	 * the file-hierarchy.
-	 */
-	while (try_again && attempts < 10000) {
-		r = archive_read_new();
-		if (r == NULL) {
-			free(p);
-			return -1;
-		}
-
-		archive_read_support_format_all(r);
-		archive_read_support_filter_all(r);
-
-		ret = archive_read_open_memory(r, p, resource_size(res));
-		if (ret != ARCHIVE_OK) {
-			fprintf(stderr, "Failed: %s\n",
-					archive_error_string(r));
-			goto fail;
-		}
-
-		try_again = 0;
-
-		while (1) {
-			ret = archive_read_next_header(r, &e);
-			if (ret == ARCHIVE_EOF)
-				break;
-			if (ret != ARCHIVE_OK)
-				goto fail;
-
-			ret = remove(archive_entry_pathname(e));
-			if (ret < 0) {
-				switch (errno) {
-				case ENOTEMPTY:
-				case EEXIST:
-					try_again = 1;
-					break;
-
-				/* should not usually happen: */
-				case ENOENT:
-				case ENOTDIR:
-				case EROFS:
-					attempts += 1;
-					continue;
-				default:
-					perror("Failed to remove file");
-					goto fail;
-				}
-			}
-		}
-
-		archive_read_free(r);
-		attempts += 1;
-	}
-
-	if (attempts >= 10000) {
-		fprintf(stderr, "Failed to remove archive\n");
-		free(p);
-		return -1;
-	}
-
-	free(p);
-	return 0;
-
-fail:
-	archive_read_free(r);
-	free(p);
-
-	rte_panic("Failed: %s\n", archive_error_string(r));
-	return -1;
-}
-
-#endif /* RTE_APP_TEST_RESOURCE_TAR */
-
-void resource_register(struct resource *r)
-{
-	TAILQ_INSERT_TAIL(&resource_list, r, next);
-}
diff --git a/app/test/resource.h b/app/test/resource.h
deleted file mode 100644
index c75ebd4b5d..0000000000
--- a/app/test/resource.h
+++ /dev/null
@@ -1,106 +0,0 @@
-/* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2016 RehiveTech. All rights reserved.
- */
-
-#ifndef _RESOURCE_H_
-#define _RESOURCE_H_
-
-/**
- * @file
- *
- * Test Resource API
- *
- * Each test can require and use some external resources. Usually, an external
- * resource is a file or a filesystem sub-hierarchy. A resource is included
- * inside the test executable.
- */
-
-#include <sys/queue.h>
-#include <stdio.h>
-#include <stddef.h>
-
-#include <rte_eal.h>
-#include <rte_common.h>
-
-TAILQ_HEAD(resource_list, resource);
-extern struct resource_list resource_list;
-
-/**
- * Representation of a resource. It points to the resource's binary data.
- * The semantics of the binary data are defined by the target test.
- */
-struct resource {
-	const char *name;  /**< Unique name of the resource */
-	const char *begin; /**< Start of resource data */
-	const char *end;   /**< End of resource data */
-	TAILQ_ENTRY(resource) next;
-};
-
-/**
- * @return size of the given resource
- */
-size_t resource_size(const struct resource *r);
-
-/**
- * Find a resource by name in the global list of resources.
- */
-const struct resource *resource_find(const char *name);
-
-/**
- * Write the raw data of the resource to the given file.
- * @return 0 on success
- */
-int resource_fwrite(const struct resource *r, FILE *f);
-
-/**
- * Write the raw data of the resource to the given file given by name.
- * The name is relative to the current working directory.
- * @return 0 on success
- */
-int resource_fwrite_file(const struct resource *r, const char *fname);
-
-/**
- * Treat the given resource as a tar archive. Extract
- * the archive to the current directory.
- */
-int resource_untar(const struct resource *res);
-
-/**
- * Treat the given resource as a tar archive. Remove
- * all files (related to the current directory) listed
- * in the tar archive.
- */
-int resource_rm_by_tar(const struct resource *res);
-
-/**
- * Register a resource in the global list of resources.
- * Not intended for direct use, please check the REGISTER_RESOURCE
- * macro.
- */
-void resource_register(struct resource *r);
-
-/**
- * Definition of a resource linked externally (by means of the used toolchain).
- * Only the base name of the resource is expected. The name refers to the
- * linked pointers beg_<name> and end_<name> provided externally.
- */
-#define REGISTER_LINKED_RESOURCE(n) \
-extern const char beg_ ##n;         \
-extern const char end_ ##n;         \
-REGISTER_RESOURCE(n, &beg_ ##n, &end_ ##n) \
-
-/**
- * Definition of a resource described by its name, and pointers begin, end.
- */
-#define REGISTER_RESOURCE(n, b, e) \
-static struct resource linkres_ ##n = {       \
-	.name = RTE_STR(n),     \
-	.begin = b,             \
-	.end = e,               \
-};                              \
-RTE_INIT(resinitfn_ ##n)	\
-{                               \
-	resource_register(&linkres_ ##n);  \
-}
-
-#endif
diff --git a/app/test/test_resource.c b/app/test/test_resource.c
deleted file mode 100644
index 05c27db203..0000000000
--- a/app/test/test_resource.c
+++ /dev/null
@@ -1,104 +0,0 @@
-/* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2016 RehiveTech. All rights reserved.
- */
-
-#include <stdio.h>
-#include <string.h>
-
-#include "test.h"
-#include "resource.h"
-
-const char test_resource_dpdk_blob[] = {
-	'\x44', '\x50', '\x44', '\x4b', '\x00'
-};
-
-REGISTER_RESOURCE(test_resource_dpdk,
-		test_resource_dpdk_blob, test_resource_dpdk_blob + 4);
-
-static int test_resource_dpdk(void)
-{
-	const struct resource *r;
-
-	r = resource_find("test_resource_dpdk");
-	TEST_ASSERT_NOT_NULL(r, "Could not find test_resource_dpdk");
-	TEST_ASSERT(!strcmp(r->name, "test_resource_dpdk"),
-			"Found resource %s, expected test_resource_dpdk",
-			r->name);
-
-	TEST_ASSERT(!strncmp("DPDK", r->begin, 4),
-			"Unexpected payload: %.4s...", r->begin);
-
-	return 0;
-}
-
-REGISTER_LINKED_RESOURCE(test_resource_c);
-
-static int test_resource_c(void)
-{
-	const struct resource *r;
-	FILE *f;
-
-	r = resource_find("test_resource_c");
-	TEST_ASSERT_NOT_NULL(r, "No test_resource_c found");
-	TEST_ASSERT(!strcmp(r->name, "test_resource_c"),
-			"Found resource %s, expected test_resource_c",
-			r->name);
-
-	TEST_ASSERT_SUCCESS(resource_fwrite_file(r, "test_resource.c"),
-			"Failed to write file %s", r->name);
-
-	f = fopen("test_resource.c", "r");
-	TEST_ASSERT_NOT_NULL(f,
-			"Missing extracted file resource.c");
-	fclose(f);
-	remove("test_resource.c");
-
-	return 0;
-}
-
-#ifdef RTE_APP_TEST_RESOURCE_TAR
-REGISTER_LINKED_RESOURCE(test_resource_tar);
-
-static int test_resource_tar(void)
-{
-	const struct resource *r;
-	FILE *f;
-
-	r = resource_find("test_resource_tar");
-	TEST_ASSERT_NOT_NULL(r, "No test_resource_tar found");
-	TEST_ASSERT(!strcmp(r->name, "test_resource_tar"),
-			"Found resource %s, expected test_resource_tar",
-			r->name);
-
-	TEST_ASSERT_SUCCESS(resource_untar(r),
-			"Failed to to untar %s", r->name);
-
-	f = fopen("test_resource.c", "r");
-	TEST_ASSERT_NOT_NULL(f,
-			"Missing extracted file test_resource.c");
-	fclose(f);
-
-	TEST_ASSERT_SUCCESS(resource_rm_by_tar(r),
-			"Failed to remove extracted contents of %s", r->name);
-	return 0;
-}
-
-#endif /* RTE_APP_TEST_RESOURCE_TAR */
-
-static int test_resource(void)
-{
-	if (test_resource_dpdk())
-		return -1;
-
-	if (test_resource_c())
-		return -1;
-
-#ifdef RTE_APP_TEST_RESOURCE_TAR
-	if (test_resource_tar())
-		return -1;
-#endif /* RTE_APP_TEST_RESOURCE_TAR */
-
-	return 0;
-}
-
-REGISTER_TEST_COMMAND(resource_autotest, test_resource);
-- 
2.43.0


^ permalink raw reply	[flat|nested] 34+ messages in thread

* [PATCH v5 3/4] test: restore cfgfile tests
  2024-08-02 16:44 ` [PATCH v5 0/4] restore unused " Stephen Hemminger
  2024-08-02 16:45   ` [PATCH v5 1/4] buildtools: add helper to convert text file to header Stephen Hemminger
  2024-08-02 16:45   ` [PATCH v5 2/4] test: remove unused resource API Stephen Hemminger
@ 2024-08-02 16:45   ` Stephen Hemminger
  2024-08-02 16:52     ` Bruce Richardson
  2024-08-02 16:45   ` [PATCH v5 4/4] test: rearrange test_cfgfiles cases Stephen Hemminger
  3 siblings, 1 reply; 34+ messages in thread
From: Stephen Hemminger @ 2024-08-02 16:45 UTC (permalink / raw)
  To: dev; +Cc: Stephen Hemminger

These tests were not built since the conversion to meson.
Instead of using embedded resource functions, put data in include
file and generate temporary file before the test.

The changes to app/test/meson.build are to handle auto-generated
files (resources) differently. Don't scan these files to look
for test input.

Using common unit test macro allows for simpler management
of more tests.

Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
 app/meson.build                    |   3 +-
 app/test/meson.build               |   6 +-
 app/test/test_cfgfile.c            | 213 ++++++++++++++++++-----------
 app/test/test_cfgfiles/meson.build |  19 +++
 4 files changed, 157 insertions(+), 84 deletions(-)
 create mode 100644 app/test/test_cfgfiles/meson.build

diff --git a/app/meson.build b/app/meson.build
index 5b2c80c7a1..e2db888ae1 100644
--- a/app/meson.build
+++ b/app/meson.build
@@ -55,6 +55,7 @@ foreach app:apps
     build = true
     reason = '<unknown reason>' # set if build == false to explain
     sources = []
+    resources = []
     includes = []
     cflags = default_cflags
     ldflags = default_ldflags
@@ -115,7 +116,7 @@ foreach app:apps
     endif
 
     exec = executable('dpdk-' + name,
-            sources,
+            [ sources, resources ],
             c_args: cflags,
             link_args: ldflags,
             link_whole: link_libs,
diff --git a/app/test/meson.build b/app/test/meson.build
index 62478c0bb6..b2bb7c36f6 100644
--- a/app/test/meson.build
+++ b/app/test/meson.build
@@ -35,7 +35,7 @@ source_file_deps = {
     'test_bitratestats.c': ['metrics', 'bitratestats', 'ethdev'] + sample_packet_forward_deps,
     'test_bpf.c': ['bpf', 'net'],
     'test_byteorder.c': [],
-#    'test_cfgfile.c': ['cfgfile'],
+    'test_cfgfile.c': ['cfgfile'],
     'test_cksum.c': ['net'],
     'test_cksum_perf.c': ['net'],
     'test_cmdline.c': [],
@@ -261,3 +261,7 @@ if not is_windows
             build_by_default: true,
             install: false)
 endif
+
+subdir('test_cfgfiles')
+
+resources += test_cfgfile_h
diff --git a/app/test/test_cfgfile.c b/app/test/test_cfgfile.c
index a5e3d8699c..8146435033 100644
--- a/app/test/test_cfgfile.c
+++ b/app/test/test_cfgfile.c
@@ -5,48 +5,54 @@
 #include <stdio.h>
 #include <string.h>
 #include <stdint.h>
-#include <sys/queue.h>
+#include <unistd.h>
+
+#ifdef RTE_EXEC_ENV_WINDOWS
+#include <io.h>
+#endif
 
 #include <rte_cfgfile.h>
 
 #include "test.h"
-#include "resource.h"
-
 
-#define CFG_FILES_ETC "test_cfgfiles/etc"
-
-REGISTER_LINKED_RESOURCE(test_cfgfiles);
+#include "test_cfgfiles.h"
 
 static int
-test_cfgfile_setup(void)
+make_tmp_file(char *filename, const char *prefix, const char *data)
 {
-	const struct resource *r;
-	int ret;
+	size_t len = strlen(data);
+	size_t count;
+	FILE *f;
 
-	r = resource_find("test_cfgfiles");
-	TEST_ASSERT_NOT_NULL(r, "missing resource test_cfgfiles");
+#ifdef RTE_EXEC_ENV_WINDOWS
+	char tempDirName[MAX_PATH - 14];
 
-	ret = resource_untar(r);
-	TEST_ASSERT_SUCCESS(ret, "failed to untar %s", r->name);
+	if (GetTempPathA(sizeof(tempDirName), tempDirName) == 0)
+		return -1;
 
-	return 0;
-}
+	if (GetTempFileNameA(tempDirName, prefix, 0, filename) == 0)
+		return -1;
 
-static int
-test_cfgfile_cleanup(void)
-{
-	const struct resource *r;
-	int ret;
+	f = fopen(filename, "wt");
+#else
+	snprintf(filename, PATH_MAX, "/tmp/%s_XXXXXXX", prefix);
 
-	r = resource_find("test_cfgfiles");
-	TEST_ASSERT_NOT_NULL(r, "missing resource test_cfgfiles");
+	int fd = mkstemp(filename);
+	if (fd < 0)
+		return -1;
 
-	ret = resource_rm_by_tar(r);
-	TEST_ASSERT_SUCCESS(ret, "Failed to delete resource %s", r->name);
+	f = fdopen(fd, "w");
+#endif
+	if (f == NULL)
+		return -1;
 
-	return 0;
+	count = fwrite(data, sizeof(char), len, f);
+	fclose(f);
+
+	return (count == len) ? 0 : -1;
 }
 
+
 static int
 _test_cfgfile_sample(struct rte_cfgfile *cfgfile)
 {
@@ -87,9 +93,13 @@ static int
 test_cfgfile_sample1(void)
 {
 	struct rte_cfgfile *cfgfile;
+	char filename[PATH_MAX];
 	int ret;
 
-	cfgfile = rte_cfgfile_load(CFG_FILES_ETC "/sample1.ini", 0);
+	ret = make_tmp_file(filename, "sample1", sample1_ini);
+	TEST_ASSERT_SUCCESS(ret, "Failed to setup temp file");
+
+	cfgfile = rte_cfgfile_load(filename, 0);
 	TEST_ASSERT_NOT_NULL(cfgfile, "Failed to load config file");
 
 	ret = _test_cfgfile_sample(cfgfile);
@@ -98,6 +108,8 @@ test_cfgfile_sample1(void)
 	ret = rte_cfgfile_close(cfgfile);
 	TEST_ASSERT_SUCCESS(ret, "Failed to close cfgfile");
 
+	remove(filename);
+
 	return 0;
 }
 
@@ -106,15 +118,18 @@ test_cfgfile_sample2(void)
 {
 	struct rte_cfgfile_parameters params;
 	struct rte_cfgfile *cfgfile;
+	char filename[PATH_MAX];
 	int ret;
 
+	ret = make_tmp_file(filename, "sample2", sample2_ini);
+	TEST_ASSERT_SUCCESS(ret, "Failed to setup temp file");
+
 	/* override comment character */
 	memset(&params, 0, sizeof(params));
 	params.comment_character = '#';
 
-	cfgfile = rte_cfgfile_load_with_params(CFG_FILES_ETC "/sample2.ini", 0,
-					       &params);
-	TEST_ASSERT_NOT_NULL(cfgfile, "Failed to parse sample2.ini");
+	cfgfile = rte_cfgfile_load_with_params(filename, 0, &params);
+	TEST_ASSERT_NOT_NULL(cfgfile, "Failed to parse sample2");
 
 	ret = _test_cfgfile_sample(cfgfile);
 	TEST_ASSERT_SUCCESS(ret, "Failed to validate sample file: %d", ret);
@@ -122,6 +137,8 @@ test_cfgfile_sample2(void)
 	ret = rte_cfgfile_close(cfgfile);
 	TEST_ASSERT_SUCCESS(ret, "Failed to close cfgfile");
 
+	remove(filename);
+
 	return 0;
 }
 
@@ -129,10 +146,14 @@ static int
 test_cfgfile_realloc_sections(void)
 {
 	struct rte_cfgfile *cfgfile;
+	char filename[PATH_MAX];
 	int ret;
 	const char *value;
 
-	cfgfile = rte_cfgfile_load(CFG_FILES_ETC "/realloc_sections.ini", 0);
+	ret = make_tmp_file(filename, "realloc", realloc_sections_ini);
+	TEST_ASSERT_SUCCESS(ret, "Failed to setup temp file");
+
+	cfgfile = rte_cfgfile_load(filename, 0);
 	TEST_ASSERT_NOT_NULL(cfgfile, "Failed to load config file");
 
 	ret = rte_cfgfile_num_sections(cfgfile, NULL, 0);
@@ -152,9 +173,18 @@ test_cfgfile_realloc_sections(void)
 	TEST_ASSERT(strcmp("value8_section9", value) == 0,
 		    "key unexpected value: %s", value);
 
-	ret = rte_cfgfile_save(cfgfile, "/tmp/cfgfile_save.ini");
-	TEST_ASSERT_SUCCESS(ret, "Failed to save *.ini file");
-	remove("/tmp/cfgfile_save.ini");
+	remove(filename);
+
+	char tmp[PATH_MAX] = "/tmp/";
+#ifdef RTE_EXEC_ENV_WINDOWS
+	ret = GetTempPathA(sizeof(tmp), tmp);
+	TEST_ASSERT(ret > 0, "Failed to get tmp directory");
+#endif
+	snprintf(filename, sizeof(filename), "%s%s", tmp, "cfg_save.ini");
+
+	ret = rte_cfgfile_save(cfgfile, filename);
+	TEST_ASSERT_SUCCESS(ret, "Failed to save to %s", filename);
+	remove(filename);
 
 	ret = rte_cfgfile_close(cfgfile);
 	TEST_ASSERT_SUCCESS(ret, "Failed to close cfgfile");
@@ -166,10 +196,16 @@ static int
 test_cfgfile_invalid_section_header(void)
 {
 	struct rte_cfgfile *cfgfile;
+	char filename[PATH_MAX];
+	int ret;
+
+	ret = make_tmp_file(filename, "invalid", invalid_section_ini);
+	TEST_ASSERT_SUCCESS(ret, "Failed to setup temp file");
 
-	cfgfile = rte_cfgfile_load(CFG_FILES_ETC "/invalid_section.ini", 0);
+	cfgfile = rte_cfgfile_load(filename, 0);
 	TEST_ASSERT_NULL(cfgfile, "Expected failure did not occur");
 
+	remove(filename);
 	return 0;
 }
 
@@ -178,15 +214,20 @@ test_cfgfile_invalid_comment(void)
 {
 	struct rte_cfgfile_parameters params;
 	struct rte_cfgfile *cfgfile;
+	char filename[PATH_MAX];
+	int ret;
 
 	/* override comment character with an invalid one */
 	memset(&params, 0, sizeof(params));
 	params.comment_character = '$';
 
-	cfgfile = rte_cfgfile_load_with_params(CFG_FILES_ETC "/sample2.ini", 0,
-					       &params);
+	ret = make_tmp_file(filename, "sample2", sample2_ini);
+	TEST_ASSERT_SUCCESS(ret, "Failed to setup temp file");
+
+	cfgfile = rte_cfgfile_load_with_params(filename, 0, &params);
 	TEST_ASSERT_NULL(cfgfile, "Expected failure did not occur");
 
+	remove(filename);
 	return 0;
 }
 
@@ -194,10 +235,16 @@ static int
 test_cfgfile_invalid_key_value_pair(void)
 {
 	struct rte_cfgfile *cfgfile;
+	char filename[PATH_MAX];
+	int ret;
+
+	ret = make_tmp_file(filename, "empty_key", empty_key_value_ini);
+	TEST_ASSERT_SUCCESS(ret, "Failed to setup temp file");
 
-	cfgfile = rte_cfgfile_load(CFG_FILES_ETC "/empty_key_value.ini", 0);
+	cfgfile = rte_cfgfile_load(filename, 0);
 	TEST_ASSERT_NULL(cfgfile, "Expected failure did not occur");
 
+	remove(filename);
 	return 0;
 }
 
@@ -206,11 +253,14 @@ test_cfgfile_empty_key_value_pair(void)
 {
 	struct rte_cfgfile *cfgfile;
 	const char *value;
+	char filename[PATH_MAX];
 	int ret;
 
-	cfgfile = rte_cfgfile_load(CFG_FILES_ETC "/empty_key_value.ini",
-				   CFG_FLAG_EMPTY_VALUES);
-	TEST_ASSERT_NOT_NULL(cfgfile, "Failed to parse empty_key_value.ini");
+	ret = make_tmp_file(filename, "empty_key_value", empty_key_value_ini);
+	TEST_ASSERT_SUCCESS(ret, "Failed to setup temp file");
+
+	cfgfile = rte_cfgfile_load(filename, CFG_FLAG_EMPTY_VALUES);
+	TEST_ASSERT_NOT_NULL(cfgfile, "Failed to parse empty_key_value");
 
 	ret = rte_cfgfile_num_sections(cfgfile, NULL, 0);
 	TEST_ASSERT(ret == 1, "Unexpected number of sections: %d", ret);
@@ -227,6 +277,7 @@ test_cfgfile_empty_key_value_pair(void)
 	ret = rte_cfgfile_close(cfgfile);
 	TEST_ASSERT_SUCCESS(ret, "Failed to close cfgfile");
 
+	remove(filename);
 	return 0;
 }
 
@@ -234,10 +285,16 @@ static int
 test_cfgfile_missing_section(void)
 {
 	struct rte_cfgfile *cfgfile;
+	char filename[PATH_MAX];
+	int ret;
+
+	ret = make_tmp_file(filename, "missing_section", missing_section_ini);
+	TEST_ASSERT_SUCCESS(ret, "Failed to setup temp file");
 
-	cfgfile = rte_cfgfile_load(CFG_FILES_ETC "/missing_section.ini", 0);
+	cfgfile = rte_cfgfile_load(filename, 0);
 	TEST_ASSERT_NULL(cfgfile, "Expected failure did not occur");
 
+	remove(filename);
 	return 0;
 }
 
@@ -246,10 +303,13 @@ test_cfgfile_global_properties(void)
 {
 	struct rte_cfgfile *cfgfile;
 	const char *value;
+	char filename[PATH_MAX];
 	int ret;
 
-	cfgfile = rte_cfgfile_load(CFG_FILES_ETC "/missing_section.ini",
-				   CFG_FLAG_GLOBAL_SECTION);
+	ret = make_tmp_file(filename, "missing_section", missing_section_ini);
+	TEST_ASSERT_SUCCESS(ret, "Failed to setup temp file");
+
+	cfgfile = rte_cfgfile_load(filename, CFG_FLAG_GLOBAL_SECTION);
 	TEST_ASSERT_NOT_NULL(cfgfile, "Failed to load config file");
 
 	ret = rte_cfgfile_num_sections(cfgfile, NULL, 0);
@@ -268,6 +328,7 @@ test_cfgfile_global_properties(void)
 	ret = rte_cfgfile_close(cfgfile);
 	TEST_ASSERT_SUCCESS(ret, "Failed to close cfgfile");
 
+	remove(filename);
 	return 0;
 }
 
@@ -275,9 +336,13 @@ static int
 test_cfgfile_empty_file(void)
 {
 	struct rte_cfgfile *cfgfile;
+	char filename[PATH_MAX];
 	int ret;
 
-	cfgfile = rte_cfgfile_load(CFG_FILES_ETC "/empty.ini", 0);
+	ret = make_tmp_file(filename, "empty", empty_ini);
+	TEST_ASSERT_SUCCESS(ret, "Failed to setup temp file");
+
+	cfgfile = rte_cfgfile_load(filename, 0);
 	TEST_ASSERT_NOT_NULL(cfgfile, "Failed to load config file");
 
 	ret = rte_cfgfile_num_sections(cfgfile, NULL, 0);
@@ -286,49 +351,33 @@ test_cfgfile_empty_file(void)
 	ret = rte_cfgfile_close(cfgfile);
 	TEST_ASSERT_SUCCESS(ret, "Failed to close cfgfile");
 
+	remove(filename);
 	return 0;
 }
 
+static struct
+unit_test_suite test_cfgfile_suite  = {
+	.suite_name = "Test Cfgfile Unit Test Suite",
+	.unit_test_cases = {
+		TEST_CASE(test_cfgfile_sample1),
+		TEST_CASE(test_cfgfile_sample2),
+		TEST_CASE(test_cfgfile_realloc_sections),
+		TEST_CASE(test_cfgfile_invalid_section_header),
+		TEST_CASE(test_cfgfile_invalid_comment),
+		TEST_CASE(test_cfgfile_invalid_key_value_pair),
+		TEST_CASE(test_cfgfile_empty_key_value_pair),
+		TEST_CASE(test_cfgfile_missing_section),
+		TEST_CASE(test_cfgfile_global_properties),
+		TEST_CASE(test_cfgfile_empty_file),
+
+		TEST_CASES_END()
+	}
+};
+
 static int
 test_cfgfile(void)
 {
-	if (test_cfgfile_setup())
-		return -1;
-
-	if (test_cfgfile_sample1())
-		return -1;
-
-	if (test_cfgfile_sample2())
-		return -1;
-
-	if (test_cfgfile_realloc_sections())
-		return -1;
-
-	if (test_cfgfile_invalid_section_header())
-		return -1;
-
-	if (test_cfgfile_invalid_comment())
-		return -1;
-
-	if (test_cfgfile_invalid_key_value_pair())
-		return -1;
-
-	if (test_cfgfile_empty_key_value_pair())
-		return -1;
-
-	if (test_cfgfile_missing_section())
-		return -1;
-
-	if (test_cfgfile_global_properties())
-		return -1;
-
-	if (test_cfgfile_empty_file())
-		return -1;
-
-	if (test_cfgfile_cleanup())
-		return -1;
-
-	return 0;
+	return unit_test_suite_runner(&test_cfgfile_suite);
 }
 
-REGISTER_TEST_COMMAND(cfgfile_autotest, test_cfgfile);
+REGISTER_FAST_TEST(cfgfile_autotest, true, true, test_cfgfile);
diff --git a/app/test/test_cfgfiles/meson.build b/app/test/test_cfgfiles/meson.build
new file mode 100644
index 0000000000..068b61044a
--- /dev/null
+++ b/app/test/test_cfgfiles/meson.build
@@ -0,0 +1,19 @@
+# SPDX-License-Identifier: BSD-3-Clause
+
+test_cfgfiles = files(
+    'etc/empty.ini',
+    'etc/empty_key_value.ini',
+    'etc/invalid_section.ini',
+    'etc/line_too_long.ini',
+    'etc/missing_section.ini',
+    'etc/realloc_sections.ini',
+    'etc/sample1.ini',
+    'etc/sample2.ini',
+)
+
+# generate the header file used in cfgfile test
+test_cfgfile_h = custom_target('test_cfgfile',
+                          output: 'test_cfgfiles.h',
+                          input: test_cfgfiles,
+                          capture: true,
+                          command: [ header_gen_cmd, '@INPUT@'])
-- 
2.43.0


^ permalink raw reply	[flat|nested] 34+ messages in thread

* [PATCH v5 4/4] test: rearrange test_cfgfiles cases
  2024-08-02 16:44 ` [PATCH v5 0/4] restore unused " Stephen Hemminger
                     ` (2 preceding siblings ...)
  2024-08-02 16:45   ` [PATCH v5 3/4] test: restore cfgfile tests Stephen Hemminger
@ 2024-08-02 16:45   ` Stephen Hemminger
  2024-08-02 16:51     ` Bruce Richardson
  3 siblings, 1 reply; 34+ messages in thread
From: Stephen Hemminger @ 2024-08-02 16:45 UTC (permalink / raw)
  To: dev; +Cc: Stephen Hemminger

The input files don't need to be in a separate subdirectory.

Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
 app/test/test_cfgfiles/{etc => }/empty.ini       |  0
 .../test_cfgfiles/{etc => }/empty_key_value.ini  |  0
 .../test_cfgfiles/{etc => }/invalid_section.ini  |  0
 .../test_cfgfiles/{etc => }/line_too_long.ini    |  0
 app/test/test_cfgfiles/meson.build               | 16 ++++++++--------
 .../test_cfgfiles/{etc => }/missing_section.ini  |  0
 .../test_cfgfiles/{etc => }/realloc_sections.ini |  0
 app/test/test_cfgfiles/{etc => }/sample1.ini     |  0
 app/test/test_cfgfiles/{etc => }/sample2.ini     |  0
 9 files changed, 8 insertions(+), 8 deletions(-)
 rename app/test/test_cfgfiles/{etc => }/empty.ini (100%)
 rename app/test/test_cfgfiles/{etc => }/empty_key_value.ini (100%)
 rename app/test/test_cfgfiles/{etc => }/invalid_section.ini (100%)
 rename app/test/test_cfgfiles/{etc => }/line_too_long.ini (100%)
 rename app/test/test_cfgfiles/{etc => }/missing_section.ini (100%)
 rename app/test/test_cfgfiles/{etc => }/realloc_sections.ini (100%)
 rename app/test/test_cfgfiles/{etc => }/sample1.ini (100%)
 rename app/test/test_cfgfiles/{etc => }/sample2.ini (100%)

diff --git a/app/test/test_cfgfiles/etc/empty.ini b/app/test/test_cfgfiles/empty.ini
similarity index 100%
rename from app/test/test_cfgfiles/etc/empty.ini
rename to app/test/test_cfgfiles/empty.ini
diff --git a/app/test/test_cfgfiles/etc/empty_key_value.ini b/app/test/test_cfgfiles/empty_key_value.ini
similarity index 100%
rename from app/test/test_cfgfiles/etc/empty_key_value.ini
rename to app/test/test_cfgfiles/empty_key_value.ini
diff --git a/app/test/test_cfgfiles/etc/invalid_section.ini b/app/test/test_cfgfiles/invalid_section.ini
similarity index 100%
rename from app/test/test_cfgfiles/etc/invalid_section.ini
rename to app/test/test_cfgfiles/invalid_section.ini
diff --git a/app/test/test_cfgfiles/etc/line_too_long.ini b/app/test/test_cfgfiles/line_too_long.ini
similarity index 100%
rename from app/test/test_cfgfiles/etc/line_too_long.ini
rename to app/test/test_cfgfiles/line_too_long.ini
diff --git a/app/test/test_cfgfiles/meson.build b/app/test/test_cfgfiles/meson.build
index 068b61044a..348c78c7d9 100644
--- a/app/test/test_cfgfiles/meson.build
+++ b/app/test/test_cfgfiles/meson.build
@@ -1,14 +1,14 @@
 # SPDX-License-Identifier: BSD-3-Clause
 
 test_cfgfiles = files(
-    'etc/empty.ini',
-    'etc/empty_key_value.ini',
-    'etc/invalid_section.ini',
-    'etc/line_too_long.ini',
-    'etc/missing_section.ini',
-    'etc/realloc_sections.ini',
-    'etc/sample1.ini',
-    'etc/sample2.ini',
+    'empty.ini',
+    'empty_key_value.ini',
+    'invalid_section.ini',
+    'line_too_long.ini',
+    'missing_section.ini',
+    'realloc_sections.ini',
+    'sample1.ini',
+    'sample2.ini',
 )
 
 # generate the header file used in cfgfile test
diff --git a/app/test/test_cfgfiles/etc/missing_section.ini b/app/test/test_cfgfiles/missing_section.ini
similarity index 100%
rename from app/test/test_cfgfiles/etc/missing_section.ini
rename to app/test/test_cfgfiles/missing_section.ini
diff --git a/app/test/test_cfgfiles/etc/realloc_sections.ini b/app/test/test_cfgfiles/realloc_sections.ini
similarity index 100%
rename from app/test/test_cfgfiles/etc/realloc_sections.ini
rename to app/test/test_cfgfiles/realloc_sections.ini
diff --git a/app/test/test_cfgfiles/etc/sample1.ini b/app/test/test_cfgfiles/sample1.ini
similarity index 100%
rename from app/test/test_cfgfiles/etc/sample1.ini
rename to app/test/test_cfgfiles/sample1.ini
diff --git a/app/test/test_cfgfiles/etc/sample2.ini b/app/test/test_cfgfiles/sample2.ini
similarity index 100%
rename from app/test/test_cfgfiles/etc/sample2.ini
rename to app/test/test_cfgfiles/sample2.ini
-- 
2.43.0


^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [PATCH v5 4/4] test: rearrange test_cfgfiles cases
  2024-08-02 16:45   ` [PATCH v5 4/4] test: rearrange test_cfgfiles cases Stephen Hemminger
@ 2024-08-02 16:51     ` Bruce Richardson
  2024-08-02 17:06       ` Stephen Hemminger
  0 siblings, 1 reply; 34+ messages in thread
From: Bruce Richardson @ 2024-08-02 16:51 UTC (permalink / raw)
  To: Stephen Hemminger; +Cc: dev

On Fri, Aug 02, 2024 at 09:45:03AM -0700, Stephen Hemminger wrote:
> The input files don't need to be in a separate subdirectory.
> 
> Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>

Small suggestion - I'd move this up to be patch 3, rather than patch 4,
which would save editing the list in the meson.build file to remove the
"etc/" prefix

Acked-by: Bruce Richardson <bruce.richardson@intel.com>
> ---
>  app/test/test_cfgfiles/{etc => }/empty.ini       |  0
>  .../test_cfgfiles/{etc => }/empty_key_value.ini  |  0
>  .../test_cfgfiles/{etc => }/invalid_section.ini  |  0
>  .../test_cfgfiles/{etc => }/line_too_long.ini    |  0
>  app/test/test_cfgfiles/meson.build               | 16 ++++++++--------
>  .../test_cfgfiles/{etc => }/missing_section.ini  |  0
>  .../test_cfgfiles/{etc => }/realloc_sections.ini |  0
>  app/test/test_cfgfiles/{etc => }/sample1.ini     |  0
>  app/test/test_cfgfiles/{etc => }/sample2.ini     |  0
>  9 files changed, 8 insertions(+), 8 deletions(-)
>  rename app/test/test_cfgfiles/{etc => }/empty.ini (100%)
>  rename app/test/test_cfgfiles/{etc => }/empty_key_value.ini (100%)
>  rename app/test/test_cfgfiles/{etc => }/invalid_section.ini (100%)
>  rename app/test/test_cfgfiles/{etc => }/line_too_long.ini (100%)
>  rename app/test/test_cfgfiles/{etc => }/missing_section.ini (100%)
>  rename app/test/test_cfgfiles/{etc => }/realloc_sections.ini (100%)
>  rename app/test/test_cfgfiles/{etc => }/sample1.ini (100%)
>  rename app/test/test_cfgfiles/{etc => }/sample2.ini (100%)
> 
> diff --git a/app/test/test_cfgfiles/etc/empty.ini b/app/test/test_cfgfiles/empty.ini
> similarity index 100%
> rename from app/test/test_cfgfiles/etc/empty.ini
> rename to app/test/test_cfgfiles/empty.ini
> diff --git a/app/test/test_cfgfiles/etc/empty_key_value.ini b/app/test/test_cfgfiles/empty_key_value.ini
> similarity index 100%
> rename from app/test/test_cfgfiles/etc/empty_key_value.ini
> rename to app/test/test_cfgfiles/empty_key_value.ini
> diff --git a/app/test/test_cfgfiles/etc/invalid_section.ini b/app/test/test_cfgfiles/invalid_section.ini
> similarity index 100%
> rename from app/test/test_cfgfiles/etc/invalid_section.ini
> rename to app/test/test_cfgfiles/invalid_section.ini
> diff --git a/app/test/test_cfgfiles/etc/line_too_long.ini b/app/test/test_cfgfiles/line_too_long.ini
> similarity index 100%
> rename from app/test/test_cfgfiles/etc/line_too_long.ini
> rename to app/test/test_cfgfiles/line_too_long.ini
> diff --git a/app/test/test_cfgfiles/meson.build b/app/test/test_cfgfiles/meson.build
> index 068b61044a..348c78c7d9 100644
> --- a/app/test/test_cfgfiles/meson.build
> +++ b/app/test/test_cfgfiles/meson.build
> @@ -1,14 +1,14 @@
>  # SPDX-License-Identifier: BSD-3-Clause
>  
>  test_cfgfiles = files(
> -    'etc/empty.ini',
> -    'etc/empty_key_value.ini',
> -    'etc/invalid_section.ini',
> -    'etc/line_too_long.ini',
> -    'etc/missing_section.ini',
> -    'etc/realloc_sections.ini',
> -    'etc/sample1.ini',
> -    'etc/sample2.ini',
> +    'empty.ini',
> +    'empty_key_value.ini',
> +    'invalid_section.ini',
> +    'line_too_long.ini',
> +    'missing_section.ini',
> +    'realloc_sections.ini',
> +    'sample1.ini',
> +    'sample2.ini',
>  )
>  
>  # generate the header file used in cfgfile test
> diff --git a/app/test/test_cfgfiles/etc/missing_section.ini b/app/test/test_cfgfiles/missing_section.ini
> similarity index 100%
> rename from app/test/test_cfgfiles/etc/missing_section.ini
> rename to app/test/test_cfgfiles/missing_section.ini
> diff --git a/app/test/test_cfgfiles/etc/realloc_sections.ini b/app/test/test_cfgfiles/realloc_sections.ini
> similarity index 100%
> rename from app/test/test_cfgfiles/etc/realloc_sections.ini
> rename to app/test/test_cfgfiles/realloc_sections.ini
> diff --git a/app/test/test_cfgfiles/etc/sample1.ini b/app/test/test_cfgfiles/sample1.ini
> similarity index 100%
> rename from app/test/test_cfgfiles/etc/sample1.ini
> rename to app/test/test_cfgfiles/sample1.ini
> diff --git a/app/test/test_cfgfiles/etc/sample2.ini b/app/test/test_cfgfiles/sample2.ini
> similarity index 100%
> rename from app/test/test_cfgfiles/etc/sample2.ini
> rename to app/test/test_cfgfiles/sample2.ini
> -- 
> 2.43.0
> 

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [PATCH v5 3/4] test: restore cfgfile tests
  2024-08-02 16:45   ` [PATCH v5 3/4] test: restore cfgfile tests Stephen Hemminger
@ 2024-08-02 16:52     ` Bruce Richardson
  0 siblings, 0 replies; 34+ messages in thread
From: Bruce Richardson @ 2024-08-02 16:52 UTC (permalink / raw)
  To: Stephen Hemminger; +Cc: dev

On Fri, Aug 02, 2024 at 09:45:02AM -0700, Stephen Hemminger wrote:
> These tests were not built since the conversion to meson.
> Instead of using embedded resource functions, put data in include
> file and generate temporary file before the test.
> 
> The changes to app/test/meson.build are to handle auto-generated
> files (resources) differently. Don't scan these files to look
> for test input.
> 
> Using common unit test macro allows for simpler management
> of more tests.
> 
> Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>


Acked-by: Bruce Richardson <bruce.richardson@intel.com>


^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [PATCH v5 4/4] test: rearrange test_cfgfiles cases
  2024-08-02 16:51     ` Bruce Richardson
@ 2024-08-02 17:06       ` Stephen Hemminger
  2024-08-06  8:37         ` Bruce Richardson
  0 siblings, 1 reply; 34+ messages in thread
From: Stephen Hemminger @ 2024-08-02 17:06 UTC (permalink / raw)
  To: Bruce Richardson; +Cc: dev

On Fri, 2 Aug 2024 17:51:01 +0100
Bruce Richardson <bruce.richardson@intel.com> wrote:

> On Fri, Aug 02, 2024 at 09:45:03AM -0700, Stephen Hemminger wrote:
> > The input files don't need to be in a separate subdirectory.
> > 
> > Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>  
> 
> Small suggestion - I'd move this up to be patch 3, rather than patch 4,
> which would save editing the list in the meson.build file to remove the
> "etc/" prefix
> 
> Acked-by: Bruce Richardson <bruce.richardson@intel.com>

Sure it would be logical to merge the two, just wanted the patches to
be smaller and easier to review 


^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [PATCH v5 4/4] test: rearrange test_cfgfiles cases
  2024-08-02 17:06       ` Stephen Hemminger
@ 2024-08-06  8:37         ` Bruce Richardson
  0 siblings, 0 replies; 34+ messages in thread
From: Bruce Richardson @ 2024-08-06  8:37 UTC (permalink / raw)
  To: Stephen Hemminger; +Cc: dev

On Fri, Aug 02, 2024 at 10:06:35AM -0700, Stephen Hemminger wrote:
> On Fri, 2 Aug 2024 17:51:01 +0100
> Bruce Richardson <bruce.richardson@intel.com> wrote:
> 
> > On Fri, Aug 02, 2024 at 09:45:03AM -0700, Stephen Hemminger wrote:
> > > The input files don't need to be in a separate subdirectory.
> > > 
> > > Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>  
> > 
> > Small suggestion - I'd move this up to be patch 3, rather than patch 4,
> > which would save editing the list in the meson.build file to remove the
> > "etc/" prefix
> > 
> > Acked-by: Bruce Richardson <bruce.richardson@intel.com>
> 
> Sure it would be logical to merge the two, just wanted the patches to
> be smaller and easier to review 
> 
I actually think they are better separate, just switch the order.

/Bruce

^ permalink raw reply	[flat|nested] 34+ messages in thread

* [PATCH v6 0/4] test: restore cfgfile lib tests
  2024-07-30 22:51 [PATCH 0/3] restore cfgfile library tests Stephen Hemminger
                   ` (6 preceding siblings ...)
  2024-08-02 16:44 ` [PATCH v5 0/4] restore unused " Stephen Hemminger
@ 2024-08-13 15:57 ` Stephen Hemminger
  2024-08-13 15:57   ` [PATCH v6 1/4] buildtools: add helper to convert text file to header Stephen Hemminger
                     ` (4 more replies)
  7 siblings, 5 replies; 34+ messages in thread
From: Stephen Hemminger @ 2024-08-13 15:57 UTC (permalink / raw)
  To: dev; +Cc: Stephen Hemminger

The cfgfile tests did not get built since conversion to meson
and they used an awkward way to manage the test data.

This patchset converts the tests to use a helper to take
text file and make it into a C header. Then use the C header
to generate temporary files as needed.

v6 - rearrange patch order for easier review

Stephen Hemminger (4):
  buildtools: add helper to convert text file to header
  test: remove unused resource API
  test: rearrange test_cfgfiles cases
  test: restore cfgfile tests

 app/meson.build                               |   3 +-
 app/test/meson.build                          |   8 +-
 app/test/resource.c                           | 276 ------------------
 app/test/resource.h                           | 106 -------
 app/test/test_cfgfile.c                       | 213 ++++++++------
 app/test/test_cfgfiles/{etc => }/empty.ini    |   0
 .../{etc => }/empty_key_value.ini             |   0
 .../{etc => }/invalid_section.ini             |   0
 .../test_cfgfiles/{etc => }/line_too_long.ini |   0
 app/test/test_cfgfiles/meson.build            |  19 ++
 .../{etc => }/missing_section.ini             |   0
 .../{etc => }/realloc_sections.ini            |   0
 app/test/test_cfgfiles/{etc => }/sample1.ini  |   0
 app/test/test_cfgfiles/{etc => }/sample2.ini  |   0
 app/test/test_resource.c                      | 104 -------
 buildtools/gen-header.py                      |  36 +++
 buildtools/meson.build                        |   2 +-
 17 files changed, 194 insertions(+), 573 deletions(-)
 delete mode 100644 app/test/resource.c
 delete mode 100644 app/test/resource.h
 rename app/test/test_cfgfiles/{etc => }/empty.ini (100%)
 rename app/test/test_cfgfiles/{etc => }/empty_key_value.ini (100%)
 rename app/test/test_cfgfiles/{etc => }/invalid_section.ini (100%)
 rename app/test/test_cfgfiles/{etc => }/line_too_long.ini (100%)
 create mode 100644 app/test/test_cfgfiles/meson.build
 rename app/test/test_cfgfiles/{etc => }/missing_section.ini (100%)
 rename app/test/test_cfgfiles/{etc => }/realloc_sections.ini (100%)
 rename app/test/test_cfgfiles/{etc => }/sample1.ini (100%)
 rename app/test/test_cfgfiles/{etc => }/sample2.ini (100%)
 delete mode 100644 app/test/test_resource.c
 create mode 100644 buildtools/gen-header.py

-- 
2.43.0


^ permalink raw reply	[flat|nested] 34+ messages in thread

* [PATCH v6 1/4] buildtools: add helper to convert text file to header
  2024-08-13 15:57 ` [PATCH v6 0/4] test: restore cfgfile lib tests Stephen Hemminger
@ 2024-08-13 15:57   ` Stephen Hemminger
  2024-08-13 15:57   ` [PATCH v6 2/4] test: remove unused resource API Stephen Hemminger
                     ` (3 subsequent siblings)
  4 siblings, 0 replies; 34+ messages in thread
From: Stephen Hemminger @ 2024-08-13 15:57 UTC (permalink / raw)
  To: dev; +Cc: Stephen Hemminger, Bruce Richardson

Simple script to read a file and make it into a initialized
C string in a header file.

Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
Acked-by: Bruce Richardson <bruce.richardson@intel.com>
---
 buildtools/gen-header.py | 36 ++++++++++++++++++++++++++++++++++++
 buildtools/meson.build   |  2 +-
 2 files changed, 37 insertions(+), 1 deletion(-)
 create mode 100644 buildtools/gen-header.py

diff --git a/buildtools/gen-header.py b/buildtools/gen-header.py
new file mode 100644
index 0000000000..06e645863c
--- /dev/null
+++ b/buildtools/gen-header.py
@@ -0,0 +1,36 @@
+#! /usr/bin/env python3
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright (c) 2023 Stephen Hemminger <stephen@networkplumber.org>
+
+"""
+Script to read a text file and convert it into a header file.
+"""
+import sys
+import os
+
+
+def main():
+    '''program main function'''
+    print(f'/* File autogenerated by {sys.argv[0]} */')
+    for path in sys.argv[1:]:
+        name = os.path.basename(path)
+        print()
+        print(f'/* generated from {name} */')
+        with open(path, "r") as f:
+            array = name.replace(".", "_")
+            print(f'static const char {array}[] = ' + '{')
+            line = f.readline()
+
+            # make sure empty string is null terminated
+            if not line:
+                print('    ""')
+
+            while line:
+                s = repr(line)
+                print('    {}'.format(s.replace("'", '"')))
+                line = f.readline()
+            print('};')
+
+
+if __name__ == "__main__":
+    main()
diff --git a/buildtools/meson.build b/buildtools/meson.build
index 3adf34e1a8..bc818a71d5 100644
--- a/buildtools/meson.build
+++ b/buildtools/meson.build
@@ -24,6 +24,7 @@ get_numa_count_cmd = py3 + files('get-numa-count.py')
 get_test_suites_cmd = py3 + files('get-test-suites.py')
 has_hugepages_cmd = py3 + files('has-hugepages.py')
 cmdline_gen_cmd = py3 + files('dpdk-cmdline-gen.py')
+header_gen_cmd = py3 + files('gen-header.py')
 
 # install any build tools that end-users might want also
 install_data([
@@ -48,4 +49,3 @@ else
     pmdinfo += 'ar'
     pmdinfogen += 'elf'
 endif
-
-- 
2.43.0


^ permalink raw reply	[flat|nested] 34+ messages in thread

* [PATCH v6 2/4] test: remove unused resource API
  2024-08-13 15:57 ` [PATCH v6 0/4] test: restore cfgfile lib tests Stephen Hemminger
  2024-08-13 15:57   ` [PATCH v6 1/4] buildtools: add helper to convert text file to header Stephen Hemminger
@ 2024-08-13 15:57   ` Stephen Hemminger
  2024-08-13 15:57   ` [PATCH v6 3/4] test: rearrange test_cfgfiles cases Stephen Hemminger
                     ` (2 subsequent siblings)
  4 siblings, 0 replies; 34+ messages in thread
From: Stephen Hemminger @ 2024-08-13 15:57 UTC (permalink / raw)
  To: dev; +Cc: Stephen Hemminger, Bruce Richardson

This API was used only for cfgfile tests and was never built
after the conversion to meson. Will be replaced by simpler
method of doing cfgfile tests.

Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
Acked-by: Bruce Richardson <bruce.richardson@intel.com>
---
 app/test/meson.build     |   2 -
 app/test/resource.c      | 276 ---------------------------------------
 app/test/resource.h      | 106 ---------------
 app/test/test_resource.c | 104 ---------------
 4 files changed, 488 deletions(-)
 delete mode 100644 app/test/resource.c
 delete mode 100644 app/test/resource.h
 delete mode 100644 app/test/test_resource.c

diff --git a/app/test/meson.build b/app/test/meson.build
index e29258e6ec..62478c0bb6 100644
--- a/app/test/meson.build
+++ b/app/test/meson.build
@@ -20,7 +20,6 @@ test_cryptodev_deps = ['bus_vdev', 'net', 'cryptodev', 'security']
 source_file_deps = {
     # The C files providing functionality to other test cases
     'packet_burst_generator.c': packet_burst_generator_deps,
-#    'resource.c': [],          # unused currently.
     'sample_packet_forward.c': sample_packet_forward_deps,
     'virtual_pmd.c': virtual_pmd_deps,
 
@@ -154,7 +153,6 @@ source_file_deps = {
     'test_reciprocal_division_perf.c': [],
     'test_red.c': ['sched'],
     'test_reorder.c': ['reorder'],
-#    'test_resource.c': [],
     'test_rib.c': ['net', 'rib'],
     'test_rib6.c': ['net', 'rib'],
     'test_ring.c': ['ptr_compress'],
diff --git a/app/test/resource.c b/app/test/resource.c
deleted file mode 100644
index 34465f1668..0000000000
--- a/app/test/resource.c
+++ /dev/null
@@ -1,276 +0,0 @@
-/* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2016 RehiveTech. All rights reserved.
- */
-
-#include <stdio.h>
-#include <string.h>
-#include <errno.h>
-#include <sys/queue.h>
-
-#include <rte_debug.h>
-
-#include "resource.h"
-
-struct resource_list resource_list = TAILQ_HEAD_INITIALIZER(resource_list);
-
-size_t resource_size(const struct resource *r)
-{
-	return r->end - r->begin;
-}
-
-const struct resource *resource_find(const char *name)
-{
-	struct resource *r;
-
-	TAILQ_FOREACH(r, &resource_list, next) {
-		RTE_VERIFY(r->name);
-
-		if (!strcmp(r->name, name))
-			return r;
-	}
-
-	return NULL;
-}
-
-int resource_fwrite(const struct resource *r, FILE *f)
-{
-	const size_t goal = resource_size(r);
-	size_t total = 0;
-
-	while (total < goal) {
-		size_t wlen = fwrite(r->begin + total, 1, goal - total, f);
-		if (wlen == 0) {
-			perror(__func__);
-			return -1;
-		}
-
-		total += wlen;
-	}
-
-	return 0;
-}
-
-int resource_fwrite_file(const struct resource *r, const char *fname)
-{
-	FILE *f;
-	int ret;
-
-	f = fopen(fname, "w");
-	if (f == NULL) {
-		perror(__func__);
-		return -1;
-	}
-
-	ret = resource_fwrite(r, f);
-	fclose(f);
-	return ret;
-}
-
-#ifdef RTE_APP_TEST_RESOURCE_TAR
-#include <archive.h>
-#include <archive_entry.h>
-
-static int do_copy(struct archive *r, struct archive *w)
-{
-	const void *buf;
-	size_t len;
-#if ARCHIVE_VERSION_NUMBER >= 3000000
-	int64_t off;
-#else
-	off_t off;
-#endif
-	int ret;
-
-	while (1) {
-		ret = archive_read_data_block(r, &buf, &len, &off);
-		if (ret == ARCHIVE_RETRY)
-			continue;
-
-		if (ret == ARCHIVE_EOF)
-			return 0;
-
-		if (ret != ARCHIVE_OK)
-			return ret;
-
-		do {
-			ret = archive_write_data_block(w, buf, len, off);
-			if (ret != ARCHIVE_OK && ret != ARCHIVE_RETRY)
-				return ret;
-		} while (ret != ARCHIVE_OK);
-	}
-}
-
-int resource_untar(const struct resource *res)
-{
-	struct archive *r;
-	struct archive *w;
-	struct archive_entry *e;
-	void *p;
-	int flags = 0;
-	int ret;
-
-	p = malloc(resource_size(res));
-	if (p == NULL)
-		rte_panic("Failed to malloc %zu B\n", resource_size(res));
-
-	memcpy(p, res->begin, resource_size(res));
-
-	r = archive_read_new();
-	if (r == NULL) {
-		free(p);
-		return -1;
-	}
-
-	archive_read_support_format_all(r);
-	archive_read_support_filter_all(r);
-
-	w = archive_write_disk_new();
-	if (w == NULL) {
-		archive_read_free(r);
-		free(p);
-		return -1;
-	}
-
-	flags |= ARCHIVE_EXTRACT_PERM;
-	flags |= ARCHIVE_EXTRACT_FFLAGS;
-	archive_write_disk_set_options(w, flags);
-	archive_write_disk_set_standard_lookup(w);
-
-	ret = archive_read_open_memory(r, p, resource_size(res));
-	if (ret != ARCHIVE_OK)
-		goto fail;
-
-	while (1) {
-		ret = archive_read_next_header(r, &e);
-		if (ret == ARCHIVE_EOF)
-			break;
-		if (ret != ARCHIVE_OK)
-			goto fail;
-
-		ret = archive_write_header(w, e);
-		if (ret == ARCHIVE_EOF)
-			break;
-		if (ret != ARCHIVE_OK)
-			goto fail;
-
-		if (archive_entry_size(e) == 0)
-			continue;
-
-		ret = do_copy(r, w);
-		if (ret != ARCHIVE_OK)
-			goto fail;
-
-		ret = archive_write_finish_entry(w);
-		if (ret != ARCHIVE_OK)
-			goto fail;
-	}
-
-	archive_write_free(w);
-	archive_read_free(r);
-	free(p);
-	return 0;
-
-fail:
-	archive_write_free(w);
-	archive_read_free(r);
-	free(p);
-	rte_panic("Failed: %s\n", archive_error_string(r));
-	return -1;
-}
-
-int resource_rm_by_tar(const struct resource *res)
-{
-	struct archive *r;
-	struct archive_entry *e;
-	void *p;
-	int try_again = 1;
-	int attempts = 0;
-	int ret;
-
-	p = malloc(resource_size(res));
-	if (p == NULL)
-		rte_panic("Failed to malloc %zu B\n", resource_size(res));
-
-	memcpy(p, res->begin, resource_size(res));
-
-	/*
-	 * If somebody creates a file somewhere inside the extracted TAR
-	 * hierarchy during a test the resource_rm_by_tar might loop
-	 * infinitely. We prevent this by adding the attempts counter there.
-	 * In normal case, max N iteration is done where N is the depth of
-	 * the file-hierarchy.
-	 */
-	while (try_again && attempts < 10000) {
-		r = archive_read_new();
-		if (r == NULL) {
-			free(p);
-			return -1;
-		}
-
-		archive_read_support_format_all(r);
-		archive_read_support_filter_all(r);
-
-		ret = archive_read_open_memory(r, p, resource_size(res));
-		if (ret != ARCHIVE_OK) {
-			fprintf(stderr, "Failed: %s\n",
-					archive_error_string(r));
-			goto fail;
-		}
-
-		try_again = 0;
-
-		while (1) {
-			ret = archive_read_next_header(r, &e);
-			if (ret == ARCHIVE_EOF)
-				break;
-			if (ret != ARCHIVE_OK)
-				goto fail;
-
-			ret = remove(archive_entry_pathname(e));
-			if (ret < 0) {
-				switch (errno) {
-				case ENOTEMPTY:
-				case EEXIST:
-					try_again = 1;
-					break;
-
-				/* should not usually happen: */
-				case ENOENT:
-				case ENOTDIR:
-				case EROFS:
-					attempts += 1;
-					continue;
-				default:
-					perror("Failed to remove file");
-					goto fail;
-				}
-			}
-		}
-
-		archive_read_free(r);
-		attempts += 1;
-	}
-
-	if (attempts >= 10000) {
-		fprintf(stderr, "Failed to remove archive\n");
-		free(p);
-		return -1;
-	}
-
-	free(p);
-	return 0;
-
-fail:
-	archive_read_free(r);
-	free(p);
-
-	rte_panic("Failed: %s\n", archive_error_string(r));
-	return -1;
-}
-
-#endif /* RTE_APP_TEST_RESOURCE_TAR */
-
-void resource_register(struct resource *r)
-{
-	TAILQ_INSERT_TAIL(&resource_list, r, next);
-}
diff --git a/app/test/resource.h b/app/test/resource.h
deleted file mode 100644
index c75ebd4b5d..0000000000
--- a/app/test/resource.h
+++ /dev/null
@@ -1,106 +0,0 @@
-/* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2016 RehiveTech. All rights reserved.
- */
-
-#ifndef _RESOURCE_H_
-#define _RESOURCE_H_
-
-/**
- * @file
- *
- * Test Resource API
- *
- * Each test can require and use some external resources. Usually, an external
- * resource is a file or a filesystem sub-hierarchy. A resource is included
- * inside the test executable.
- */
-
-#include <sys/queue.h>
-#include <stdio.h>
-#include <stddef.h>
-
-#include <rte_eal.h>
-#include <rte_common.h>
-
-TAILQ_HEAD(resource_list, resource);
-extern struct resource_list resource_list;
-
-/**
- * Representation of a resource. It points to the resource's binary data.
- * The semantics of the binary data are defined by the target test.
- */
-struct resource {
-	const char *name;  /**< Unique name of the resource */
-	const char *begin; /**< Start of resource data */
-	const char *end;   /**< End of resource data */
-	TAILQ_ENTRY(resource) next;
-};
-
-/**
- * @return size of the given resource
- */
-size_t resource_size(const struct resource *r);
-
-/**
- * Find a resource by name in the global list of resources.
- */
-const struct resource *resource_find(const char *name);
-
-/**
- * Write the raw data of the resource to the given file.
- * @return 0 on success
- */
-int resource_fwrite(const struct resource *r, FILE *f);
-
-/**
- * Write the raw data of the resource to the given file given by name.
- * The name is relative to the current working directory.
- * @return 0 on success
- */
-int resource_fwrite_file(const struct resource *r, const char *fname);
-
-/**
- * Treat the given resource as a tar archive. Extract
- * the archive to the current directory.
- */
-int resource_untar(const struct resource *res);
-
-/**
- * Treat the given resource as a tar archive. Remove
- * all files (related to the current directory) listed
- * in the tar archive.
- */
-int resource_rm_by_tar(const struct resource *res);
-
-/**
- * Register a resource in the global list of resources.
- * Not intended for direct use, please check the REGISTER_RESOURCE
- * macro.
- */
-void resource_register(struct resource *r);
-
-/**
- * Definition of a resource linked externally (by means of the used toolchain).
- * Only the base name of the resource is expected. The name refers to the
- * linked pointers beg_<name> and end_<name> provided externally.
- */
-#define REGISTER_LINKED_RESOURCE(n) \
-extern const char beg_ ##n;         \
-extern const char end_ ##n;         \
-REGISTER_RESOURCE(n, &beg_ ##n, &end_ ##n) \
-
-/**
- * Definition of a resource described by its name, and pointers begin, end.
- */
-#define REGISTER_RESOURCE(n, b, e) \
-static struct resource linkres_ ##n = {       \
-	.name = RTE_STR(n),     \
-	.begin = b,             \
-	.end = e,               \
-};                              \
-RTE_INIT(resinitfn_ ##n)	\
-{                               \
-	resource_register(&linkres_ ##n);  \
-}
-
-#endif
diff --git a/app/test/test_resource.c b/app/test/test_resource.c
deleted file mode 100644
index 05c27db203..0000000000
--- a/app/test/test_resource.c
+++ /dev/null
@@ -1,104 +0,0 @@
-/* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2016 RehiveTech. All rights reserved.
- */
-
-#include <stdio.h>
-#include <string.h>
-
-#include "test.h"
-#include "resource.h"
-
-const char test_resource_dpdk_blob[] = {
-	'\x44', '\x50', '\x44', '\x4b', '\x00'
-};
-
-REGISTER_RESOURCE(test_resource_dpdk,
-		test_resource_dpdk_blob, test_resource_dpdk_blob + 4);
-
-static int test_resource_dpdk(void)
-{
-	const struct resource *r;
-
-	r = resource_find("test_resource_dpdk");
-	TEST_ASSERT_NOT_NULL(r, "Could not find test_resource_dpdk");
-	TEST_ASSERT(!strcmp(r->name, "test_resource_dpdk"),
-			"Found resource %s, expected test_resource_dpdk",
-			r->name);
-
-	TEST_ASSERT(!strncmp("DPDK", r->begin, 4),
-			"Unexpected payload: %.4s...", r->begin);
-
-	return 0;
-}
-
-REGISTER_LINKED_RESOURCE(test_resource_c);
-
-static int test_resource_c(void)
-{
-	const struct resource *r;
-	FILE *f;
-
-	r = resource_find("test_resource_c");
-	TEST_ASSERT_NOT_NULL(r, "No test_resource_c found");
-	TEST_ASSERT(!strcmp(r->name, "test_resource_c"),
-			"Found resource %s, expected test_resource_c",
-			r->name);
-
-	TEST_ASSERT_SUCCESS(resource_fwrite_file(r, "test_resource.c"),
-			"Failed to write file %s", r->name);
-
-	f = fopen("test_resource.c", "r");
-	TEST_ASSERT_NOT_NULL(f,
-			"Missing extracted file resource.c");
-	fclose(f);
-	remove("test_resource.c");
-
-	return 0;
-}
-
-#ifdef RTE_APP_TEST_RESOURCE_TAR
-REGISTER_LINKED_RESOURCE(test_resource_tar);
-
-static int test_resource_tar(void)
-{
-	const struct resource *r;
-	FILE *f;
-
-	r = resource_find("test_resource_tar");
-	TEST_ASSERT_NOT_NULL(r, "No test_resource_tar found");
-	TEST_ASSERT(!strcmp(r->name, "test_resource_tar"),
-			"Found resource %s, expected test_resource_tar",
-			r->name);
-
-	TEST_ASSERT_SUCCESS(resource_untar(r),
-			"Failed to to untar %s", r->name);
-
-	f = fopen("test_resource.c", "r");
-	TEST_ASSERT_NOT_NULL(f,
-			"Missing extracted file test_resource.c");
-	fclose(f);
-
-	TEST_ASSERT_SUCCESS(resource_rm_by_tar(r),
-			"Failed to remove extracted contents of %s", r->name);
-	return 0;
-}
-
-#endif /* RTE_APP_TEST_RESOURCE_TAR */
-
-static int test_resource(void)
-{
-	if (test_resource_dpdk())
-		return -1;
-
-	if (test_resource_c())
-		return -1;
-
-#ifdef RTE_APP_TEST_RESOURCE_TAR
-	if (test_resource_tar())
-		return -1;
-#endif /* RTE_APP_TEST_RESOURCE_TAR */
-
-	return 0;
-}
-
-REGISTER_TEST_COMMAND(resource_autotest, test_resource);
-- 
2.43.0


^ permalink raw reply	[flat|nested] 34+ messages in thread

* [PATCH v6 3/4] test: rearrange test_cfgfiles cases
  2024-08-13 15:57 ` [PATCH v6 0/4] test: restore cfgfile lib tests Stephen Hemminger
  2024-08-13 15:57   ` [PATCH v6 1/4] buildtools: add helper to convert text file to header Stephen Hemminger
  2024-08-13 15:57   ` [PATCH v6 2/4] test: remove unused resource API Stephen Hemminger
@ 2024-08-13 15:57   ` Stephen Hemminger
  2024-08-13 15:57   ` [PATCH v6 4/4] test: restore cfgfile tests Stephen Hemminger
  2024-11-19 21:53   ` [PATCH v6 0/4] test: restore cfgfile lib tests Thomas Monjalon
  4 siblings, 0 replies; 34+ messages in thread
From: Stephen Hemminger @ 2024-08-13 15:57 UTC (permalink / raw)
  To: dev; +Cc: Stephen Hemminger, Bruce Richardson, Cristian Dumitrescu

The input files don't need to be in a separate subdirectory.

Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
Acked-by: Bruce Richardson <bruce.richardson@intel.com>
---
 app/test/test_cfgfiles/{etc => }/empty.ini            | 0
 app/test/test_cfgfiles/{etc => }/empty_key_value.ini  | 0
 app/test/test_cfgfiles/{etc => }/invalid_section.ini  | 0
 app/test/test_cfgfiles/{etc => }/line_too_long.ini    | 0
 app/test/test_cfgfiles/{etc => }/missing_section.ini  | 0
 app/test/test_cfgfiles/{etc => }/realloc_sections.ini | 0
 app/test/test_cfgfiles/{etc => }/sample1.ini          | 0
 app/test/test_cfgfiles/{etc => }/sample2.ini          | 0
 8 files changed, 0 insertions(+), 0 deletions(-)
 rename app/test/test_cfgfiles/{etc => }/empty.ini (100%)
 rename app/test/test_cfgfiles/{etc => }/empty_key_value.ini (100%)
 rename app/test/test_cfgfiles/{etc => }/invalid_section.ini (100%)
 rename app/test/test_cfgfiles/{etc => }/line_too_long.ini (100%)
 rename app/test/test_cfgfiles/{etc => }/missing_section.ini (100%)
 rename app/test/test_cfgfiles/{etc => }/realloc_sections.ini (100%)
 rename app/test/test_cfgfiles/{etc => }/sample1.ini (100%)
 rename app/test/test_cfgfiles/{etc => }/sample2.ini (100%)

diff --git a/app/test/test_cfgfiles/etc/empty.ini b/app/test/test_cfgfiles/empty.ini
similarity index 100%
rename from app/test/test_cfgfiles/etc/empty.ini
rename to app/test/test_cfgfiles/empty.ini
diff --git a/app/test/test_cfgfiles/etc/empty_key_value.ini b/app/test/test_cfgfiles/empty_key_value.ini
similarity index 100%
rename from app/test/test_cfgfiles/etc/empty_key_value.ini
rename to app/test/test_cfgfiles/empty_key_value.ini
diff --git a/app/test/test_cfgfiles/etc/invalid_section.ini b/app/test/test_cfgfiles/invalid_section.ini
similarity index 100%
rename from app/test/test_cfgfiles/etc/invalid_section.ini
rename to app/test/test_cfgfiles/invalid_section.ini
diff --git a/app/test/test_cfgfiles/etc/line_too_long.ini b/app/test/test_cfgfiles/line_too_long.ini
similarity index 100%
rename from app/test/test_cfgfiles/etc/line_too_long.ini
rename to app/test/test_cfgfiles/line_too_long.ini
diff --git a/app/test/test_cfgfiles/etc/missing_section.ini b/app/test/test_cfgfiles/missing_section.ini
similarity index 100%
rename from app/test/test_cfgfiles/etc/missing_section.ini
rename to app/test/test_cfgfiles/missing_section.ini
diff --git a/app/test/test_cfgfiles/etc/realloc_sections.ini b/app/test/test_cfgfiles/realloc_sections.ini
similarity index 100%
rename from app/test/test_cfgfiles/etc/realloc_sections.ini
rename to app/test/test_cfgfiles/realloc_sections.ini
diff --git a/app/test/test_cfgfiles/etc/sample1.ini b/app/test/test_cfgfiles/sample1.ini
similarity index 100%
rename from app/test/test_cfgfiles/etc/sample1.ini
rename to app/test/test_cfgfiles/sample1.ini
diff --git a/app/test/test_cfgfiles/etc/sample2.ini b/app/test/test_cfgfiles/sample2.ini
similarity index 100%
rename from app/test/test_cfgfiles/etc/sample2.ini
rename to app/test/test_cfgfiles/sample2.ini
-- 
2.43.0


^ permalink raw reply	[flat|nested] 34+ messages in thread

* [PATCH v6 4/4] test: restore cfgfile tests
  2024-08-13 15:57 ` [PATCH v6 0/4] test: restore cfgfile lib tests Stephen Hemminger
                     ` (2 preceding siblings ...)
  2024-08-13 15:57   ` [PATCH v6 3/4] test: rearrange test_cfgfiles cases Stephen Hemminger
@ 2024-08-13 15:57   ` Stephen Hemminger
  2024-11-19 21:53   ` [PATCH v6 0/4] test: restore cfgfile lib tests Thomas Monjalon
  4 siblings, 0 replies; 34+ messages in thread
From: Stephen Hemminger @ 2024-08-13 15:57 UTC (permalink / raw)
  To: dev; +Cc: Stephen Hemminger, Bruce Richardson, Cristian Dumitrescu

These tests were not built since the conversion to meson.
Instead of using embedded resource functions, put data in include
file and generate temporary file before the test.

The changes to app/test/meson.build are to handle auto-generated
files (resources) differently. Don't scan these files to look
for test input.

Using common unit test macro allows for simpler management
of more tests.

Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
Acked-by: Bruce Richardson <bruce.richardson@intel.com>

---
 app/meson.build                    |   3 +-
 app/test/meson.build               |   6 +-
 app/test/test_cfgfile.c            | 213 ++++++++++++++++++-----------
 app/test/test_cfgfiles/meson.build |  19 +++
 4 files changed, 157 insertions(+), 84 deletions(-)
 create mode 100644 app/test/test_cfgfiles/meson.build

diff --git a/app/meson.build b/app/meson.build
index 5b2c80c7a1..e2db888ae1 100644
--- a/app/meson.build
+++ b/app/meson.build
@@ -55,6 +55,7 @@ foreach app:apps
     build = true
     reason = '<unknown reason>' # set if build == false to explain
     sources = []
+    resources = []
     includes = []
     cflags = default_cflags
     ldflags = default_ldflags
@@ -115,7 +116,7 @@ foreach app:apps
     endif
 
     exec = executable('dpdk-' + name,
-            sources,
+            [ sources, resources ],
             c_args: cflags,
             link_args: ldflags,
             link_whole: link_libs,
diff --git a/app/test/meson.build b/app/test/meson.build
index 62478c0bb6..b2bb7c36f6 100644
--- a/app/test/meson.build
+++ b/app/test/meson.build
@@ -35,7 +35,7 @@ source_file_deps = {
     'test_bitratestats.c': ['metrics', 'bitratestats', 'ethdev'] + sample_packet_forward_deps,
     'test_bpf.c': ['bpf', 'net'],
     'test_byteorder.c': [],
-#    'test_cfgfile.c': ['cfgfile'],
+    'test_cfgfile.c': ['cfgfile'],
     'test_cksum.c': ['net'],
     'test_cksum_perf.c': ['net'],
     'test_cmdline.c': [],
@@ -261,3 +261,7 @@ if not is_windows
             build_by_default: true,
             install: false)
 endif
+
+subdir('test_cfgfiles')
+
+resources += test_cfgfile_h
diff --git a/app/test/test_cfgfile.c b/app/test/test_cfgfile.c
index a5e3d8699c..8146435033 100644
--- a/app/test/test_cfgfile.c
+++ b/app/test/test_cfgfile.c
@@ -5,48 +5,54 @@
 #include <stdio.h>
 #include <string.h>
 #include <stdint.h>
-#include <sys/queue.h>
+#include <unistd.h>
+
+#ifdef RTE_EXEC_ENV_WINDOWS
+#include <io.h>
+#endif
 
 #include <rte_cfgfile.h>
 
 #include "test.h"
-#include "resource.h"
-
 
-#define CFG_FILES_ETC "test_cfgfiles/etc"
-
-REGISTER_LINKED_RESOURCE(test_cfgfiles);
+#include "test_cfgfiles.h"
 
 static int
-test_cfgfile_setup(void)
+make_tmp_file(char *filename, const char *prefix, const char *data)
 {
-	const struct resource *r;
-	int ret;
+	size_t len = strlen(data);
+	size_t count;
+	FILE *f;
 
-	r = resource_find("test_cfgfiles");
-	TEST_ASSERT_NOT_NULL(r, "missing resource test_cfgfiles");
+#ifdef RTE_EXEC_ENV_WINDOWS
+	char tempDirName[MAX_PATH - 14];
 
-	ret = resource_untar(r);
-	TEST_ASSERT_SUCCESS(ret, "failed to untar %s", r->name);
+	if (GetTempPathA(sizeof(tempDirName), tempDirName) == 0)
+		return -1;
 
-	return 0;
-}
+	if (GetTempFileNameA(tempDirName, prefix, 0, filename) == 0)
+		return -1;
 
-static int
-test_cfgfile_cleanup(void)
-{
-	const struct resource *r;
-	int ret;
+	f = fopen(filename, "wt");
+#else
+	snprintf(filename, PATH_MAX, "/tmp/%s_XXXXXXX", prefix);
 
-	r = resource_find("test_cfgfiles");
-	TEST_ASSERT_NOT_NULL(r, "missing resource test_cfgfiles");
+	int fd = mkstemp(filename);
+	if (fd < 0)
+		return -1;
 
-	ret = resource_rm_by_tar(r);
-	TEST_ASSERT_SUCCESS(ret, "Failed to delete resource %s", r->name);
+	f = fdopen(fd, "w");
+#endif
+	if (f == NULL)
+		return -1;
 
-	return 0;
+	count = fwrite(data, sizeof(char), len, f);
+	fclose(f);
+
+	return (count == len) ? 0 : -1;
 }
 
+
 static int
 _test_cfgfile_sample(struct rte_cfgfile *cfgfile)
 {
@@ -87,9 +93,13 @@ static int
 test_cfgfile_sample1(void)
 {
 	struct rte_cfgfile *cfgfile;
+	char filename[PATH_MAX];
 	int ret;
 
-	cfgfile = rte_cfgfile_load(CFG_FILES_ETC "/sample1.ini", 0);
+	ret = make_tmp_file(filename, "sample1", sample1_ini);
+	TEST_ASSERT_SUCCESS(ret, "Failed to setup temp file");
+
+	cfgfile = rte_cfgfile_load(filename, 0);
 	TEST_ASSERT_NOT_NULL(cfgfile, "Failed to load config file");
 
 	ret = _test_cfgfile_sample(cfgfile);
@@ -98,6 +108,8 @@ test_cfgfile_sample1(void)
 	ret = rte_cfgfile_close(cfgfile);
 	TEST_ASSERT_SUCCESS(ret, "Failed to close cfgfile");
 
+	remove(filename);
+
 	return 0;
 }
 
@@ -106,15 +118,18 @@ test_cfgfile_sample2(void)
 {
 	struct rte_cfgfile_parameters params;
 	struct rte_cfgfile *cfgfile;
+	char filename[PATH_MAX];
 	int ret;
 
+	ret = make_tmp_file(filename, "sample2", sample2_ini);
+	TEST_ASSERT_SUCCESS(ret, "Failed to setup temp file");
+
 	/* override comment character */
 	memset(&params, 0, sizeof(params));
 	params.comment_character = '#';
 
-	cfgfile = rte_cfgfile_load_with_params(CFG_FILES_ETC "/sample2.ini", 0,
-					       &params);
-	TEST_ASSERT_NOT_NULL(cfgfile, "Failed to parse sample2.ini");
+	cfgfile = rte_cfgfile_load_with_params(filename, 0, &params);
+	TEST_ASSERT_NOT_NULL(cfgfile, "Failed to parse sample2");
 
 	ret = _test_cfgfile_sample(cfgfile);
 	TEST_ASSERT_SUCCESS(ret, "Failed to validate sample file: %d", ret);
@@ -122,6 +137,8 @@ test_cfgfile_sample2(void)
 	ret = rte_cfgfile_close(cfgfile);
 	TEST_ASSERT_SUCCESS(ret, "Failed to close cfgfile");
 
+	remove(filename);
+
 	return 0;
 }
 
@@ -129,10 +146,14 @@ static int
 test_cfgfile_realloc_sections(void)
 {
 	struct rte_cfgfile *cfgfile;
+	char filename[PATH_MAX];
 	int ret;
 	const char *value;
 
-	cfgfile = rte_cfgfile_load(CFG_FILES_ETC "/realloc_sections.ini", 0);
+	ret = make_tmp_file(filename, "realloc", realloc_sections_ini);
+	TEST_ASSERT_SUCCESS(ret, "Failed to setup temp file");
+
+	cfgfile = rte_cfgfile_load(filename, 0);
 	TEST_ASSERT_NOT_NULL(cfgfile, "Failed to load config file");
 
 	ret = rte_cfgfile_num_sections(cfgfile, NULL, 0);
@@ -152,9 +173,18 @@ test_cfgfile_realloc_sections(void)
 	TEST_ASSERT(strcmp("value8_section9", value) == 0,
 		    "key unexpected value: %s", value);
 
-	ret = rte_cfgfile_save(cfgfile, "/tmp/cfgfile_save.ini");
-	TEST_ASSERT_SUCCESS(ret, "Failed to save *.ini file");
-	remove("/tmp/cfgfile_save.ini");
+	remove(filename);
+
+	char tmp[PATH_MAX] = "/tmp/";
+#ifdef RTE_EXEC_ENV_WINDOWS
+	ret = GetTempPathA(sizeof(tmp), tmp);
+	TEST_ASSERT(ret > 0, "Failed to get tmp directory");
+#endif
+	snprintf(filename, sizeof(filename), "%s%s", tmp, "cfg_save.ini");
+
+	ret = rte_cfgfile_save(cfgfile, filename);
+	TEST_ASSERT_SUCCESS(ret, "Failed to save to %s", filename);
+	remove(filename);
 
 	ret = rte_cfgfile_close(cfgfile);
 	TEST_ASSERT_SUCCESS(ret, "Failed to close cfgfile");
@@ -166,10 +196,16 @@ static int
 test_cfgfile_invalid_section_header(void)
 {
 	struct rte_cfgfile *cfgfile;
+	char filename[PATH_MAX];
+	int ret;
+
+	ret = make_tmp_file(filename, "invalid", invalid_section_ini);
+	TEST_ASSERT_SUCCESS(ret, "Failed to setup temp file");
 
-	cfgfile = rte_cfgfile_load(CFG_FILES_ETC "/invalid_section.ini", 0);
+	cfgfile = rte_cfgfile_load(filename, 0);
 	TEST_ASSERT_NULL(cfgfile, "Expected failure did not occur");
 
+	remove(filename);
 	return 0;
 }
 
@@ -178,15 +214,20 @@ test_cfgfile_invalid_comment(void)
 {
 	struct rte_cfgfile_parameters params;
 	struct rte_cfgfile *cfgfile;
+	char filename[PATH_MAX];
+	int ret;
 
 	/* override comment character with an invalid one */
 	memset(&params, 0, sizeof(params));
 	params.comment_character = '$';
 
-	cfgfile = rte_cfgfile_load_with_params(CFG_FILES_ETC "/sample2.ini", 0,
-					       &params);
+	ret = make_tmp_file(filename, "sample2", sample2_ini);
+	TEST_ASSERT_SUCCESS(ret, "Failed to setup temp file");
+
+	cfgfile = rte_cfgfile_load_with_params(filename, 0, &params);
 	TEST_ASSERT_NULL(cfgfile, "Expected failure did not occur");
 
+	remove(filename);
 	return 0;
 }
 
@@ -194,10 +235,16 @@ static int
 test_cfgfile_invalid_key_value_pair(void)
 {
 	struct rte_cfgfile *cfgfile;
+	char filename[PATH_MAX];
+	int ret;
+
+	ret = make_tmp_file(filename, "empty_key", empty_key_value_ini);
+	TEST_ASSERT_SUCCESS(ret, "Failed to setup temp file");
 
-	cfgfile = rte_cfgfile_load(CFG_FILES_ETC "/empty_key_value.ini", 0);
+	cfgfile = rte_cfgfile_load(filename, 0);
 	TEST_ASSERT_NULL(cfgfile, "Expected failure did not occur");
 
+	remove(filename);
 	return 0;
 }
 
@@ -206,11 +253,14 @@ test_cfgfile_empty_key_value_pair(void)
 {
 	struct rte_cfgfile *cfgfile;
 	const char *value;
+	char filename[PATH_MAX];
 	int ret;
 
-	cfgfile = rte_cfgfile_load(CFG_FILES_ETC "/empty_key_value.ini",
-				   CFG_FLAG_EMPTY_VALUES);
-	TEST_ASSERT_NOT_NULL(cfgfile, "Failed to parse empty_key_value.ini");
+	ret = make_tmp_file(filename, "empty_key_value", empty_key_value_ini);
+	TEST_ASSERT_SUCCESS(ret, "Failed to setup temp file");
+
+	cfgfile = rte_cfgfile_load(filename, CFG_FLAG_EMPTY_VALUES);
+	TEST_ASSERT_NOT_NULL(cfgfile, "Failed to parse empty_key_value");
 
 	ret = rte_cfgfile_num_sections(cfgfile, NULL, 0);
 	TEST_ASSERT(ret == 1, "Unexpected number of sections: %d", ret);
@@ -227,6 +277,7 @@ test_cfgfile_empty_key_value_pair(void)
 	ret = rte_cfgfile_close(cfgfile);
 	TEST_ASSERT_SUCCESS(ret, "Failed to close cfgfile");
 
+	remove(filename);
 	return 0;
 }
 
@@ -234,10 +285,16 @@ static int
 test_cfgfile_missing_section(void)
 {
 	struct rte_cfgfile *cfgfile;
+	char filename[PATH_MAX];
+	int ret;
+
+	ret = make_tmp_file(filename, "missing_section", missing_section_ini);
+	TEST_ASSERT_SUCCESS(ret, "Failed to setup temp file");
 
-	cfgfile = rte_cfgfile_load(CFG_FILES_ETC "/missing_section.ini", 0);
+	cfgfile = rte_cfgfile_load(filename, 0);
 	TEST_ASSERT_NULL(cfgfile, "Expected failure did not occur");
 
+	remove(filename);
 	return 0;
 }
 
@@ -246,10 +303,13 @@ test_cfgfile_global_properties(void)
 {
 	struct rte_cfgfile *cfgfile;
 	const char *value;
+	char filename[PATH_MAX];
 	int ret;
 
-	cfgfile = rte_cfgfile_load(CFG_FILES_ETC "/missing_section.ini",
-				   CFG_FLAG_GLOBAL_SECTION);
+	ret = make_tmp_file(filename, "missing_section", missing_section_ini);
+	TEST_ASSERT_SUCCESS(ret, "Failed to setup temp file");
+
+	cfgfile = rte_cfgfile_load(filename, CFG_FLAG_GLOBAL_SECTION);
 	TEST_ASSERT_NOT_NULL(cfgfile, "Failed to load config file");
 
 	ret = rte_cfgfile_num_sections(cfgfile, NULL, 0);
@@ -268,6 +328,7 @@ test_cfgfile_global_properties(void)
 	ret = rte_cfgfile_close(cfgfile);
 	TEST_ASSERT_SUCCESS(ret, "Failed to close cfgfile");
 
+	remove(filename);
 	return 0;
 }
 
@@ -275,9 +336,13 @@ static int
 test_cfgfile_empty_file(void)
 {
 	struct rte_cfgfile *cfgfile;
+	char filename[PATH_MAX];
 	int ret;
 
-	cfgfile = rte_cfgfile_load(CFG_FILES_ETC "/empty.ini", 0);
+	ret = make_tmp_file(filename, "empty", empty_ini);
+	TEST_ASSERT_SUCCESS(ret, "Failed to setup temp file");
+
+	cfgfile = rte_cfgfile_load(filename, 0);
 	TEST_ASSERT_NOT_NULL(cfgfile, "Failed to load config file");
 
 	ret = rte_cfgfile_num_sections(cfgfile, NULL, 0);
@@ -286,49 +351,33 @@ test_cfgfile_empty_file(void)
 	ret = rte_cfgfile_close(cfgfile);
 	TEST_ASSERT_SUCCESS(ret, "Failed to close cfgfile");
 
+	remove(filename);
 	return 0;
 }
 
+static struct
+unit_test_suite test_cfgfile_suite  = {
+	.suite_name = "Test Cfgfile Unit Test Suite",
+	.unit_test_cases = {
+		TEST_CASE(test_cfgfile_sample1),
+		TEST_CASE(test_cfgfile_sample2),
+		TEST_CASE(test_cfgfile_realloc_sections),
+		TEST_CASE(test_cfgfile_invalid_section_header),
+		TEST_CASE(test_cfgfile_invalid_comment),
+		TEST_CASE(test_cfgfile_invalid_key_value_pair),
+		TEST_CASE(test_cfgfile_empty_key_value_pair),
+		TEST_CASE(test_cfgfile_missing_section),
+		TEST_CASE(test_cfgfile_global_properties),
+		TEST_CASE(test_cfgfile_empty_file),
+
+		TEST_CASES_END()
+	}
+};
+
 static int
 test_cfgfile(void)
 {
-	if (test_cfgfile_setup())
-		return -1;
-
-	if (test_cfgfile_sample1())
-		return -1;
-
-	if (test_cfgfile_sample2())
-		return -1;
-
-	if (test_cfgfile_realloc_sections())
-		return -1;
-
-	if (test_cfgfile_invalid_section_header())
-		return -1;
-
-	if (test_cfgfile_invalid_comment())
-		return -1;
-
-	if (test_cfgfile_invalid_key_value_pair())
-		return -1;
-
-	if (test_cfgfile_empty_key_value_pair())
-		return -1;
-
-	if (test_cfgfile_missing_section())
-		return -1;
-
-	if (test_cfgfile_global_properties())
-		return -1;
-
-	if (test_cfgfile_empty_file())
-		return -1;
-
-	if (test_cfgfile_cleanup())
-		return -1;
-
-	return 0;
+	return unit_test_suite_runner(&test_cfgfile_suite);
 }
 
-REGISTER_TEST_COMMAND(cfgfile_autotest, test_cfgfile);
+REGISTER_FAST_TEST(cfgfile_autotest, true, true, test_cfgfile);
diff --git a/app/test/test_cfgfiles/meson.build b/app/test/test_cfgfiles/meson.build
new file mode 100644
index 0000000000..348c78c7d9
--- /dev/null
+++ b/app/test/test_cfgfiles/meson.build
@@ -0,0 +1,19 @@
+# SPDX-License-Identifier: BSD-3-Clause
+
+test_cfgfiles = files(
+    'empty.ini',
+    'empty_key_value.ini',
+    'invalid_section.ini',
+    'line_too_long.ini',
+    'missing_section.ini',
+    'realloc_sections.ini',
+    'sample1.ini',
+    'sample2.ini',
+)
+
+# generate the header file used in cfgfile test
+test_cfgfile_h = custom_target('test_cfgfile',
+                          output: 'test_cfgfiles.h',
+                          input: test_cfgfiles,
+                          capture: true,
+                          command: [ header_gen_cmd, '@INPUT@'])
-- 
2.43.0


^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [PATCH v6 0/4] test: restore cfgfile lib tests
  2024-08-13 15:57 ` [PATCH v6 0/4] test: restore cfgfile lib tests Stephen Hemminger
                     ` (3 preceding siblings ...)
  2024-08-13 15:57   ` [PATCH v6 4/4] test: restore cfgfile tests Stephen Hemminger
@ 2024-11-19 21:53   ` Thomas Monjalon
  4 siblings, 0 replies; 34+ messages in thread
From: Thomas Monjalon @ 2024-11-19 21:53 UTC (permalink / raw)
  To: Stephen Hemminger; +Cc: dev

13/08/2024 17:57, Stephen Hemminger:
> The cfgfile tests did not get built since conversion to meson
> and they used an awkward way to manage the test data.
> 
> This patchset converts the tests to use a helper to take
> text file and make it into a C header. Then use the C header
> to generate temporary files as needed.
> 
> v6 - rearrange patch order for easier review
> 
> Stephen Hemminger (4):
>   buildtools: add helper to convert text file to header
>   test: remove unused resource API
>   test: rearrange test_cfgfiles cases
>   test: restore cfgfile tests

Applied with some fixes in the file MAINTAINERS, thanks.




^ permalink raw reply	[flat|nested] 34+ messages in thread

end of thread, other threads:[~2024-11-19 21:53 UTC | newest]

Thread overview: 34+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-07-30 22:51 [PATCH 0/3] restore cfgfile library tests Stephen Hemminger
2024-07-30 22:51 ` [PATCH 1/3] buildtools: add helper to convert text file to header Stephen Hemminger
2024-07-30 22:51 ` [PATCH 2/3] test: restore cfgfile tests Stephen Hemminger
2024-07-30 22:51 ` [PATCH 3/3] test: remove unused resource API Stephen Hemminger
2024-07-31  4:20 ` [PATCH v2 0/3] restore cfgfile library tests Stephen Hemminger
2024-07-31  4:20   ` [PATCH v2 1/3] buildtools: add helper to convert text file to header Stephen Hemminger
2024-07-31  4:20   ` [PATCH v2 2/3] test: restore cfgfile tests Stephen Hemminger
2024-07-31  4:20   ` [PATCH v2 3/3] test: remove unused resource API Stephen Hemminger
2024-07-31 17:35 ` [PATCH v3 0/3] restore lost tests for rte_cfgfile Stephen Hemminger
2024-07-31 17:35   ` [PATCH v3 1/3] buildtools: add helper to convert text file to header Stephen Hemminger
2024-07-31 17:35   ` [PATCH v3 2/3] test: remove unused resource API Stephen Hemminger
2024-07-31 17:35   ` [PATCH v3 3/3] test: restore cfgfile tests Stephen Hemminger
2024-08-01 17:29 ` [PATCH v4 0/3] restore lost " Stephen Hemminger
2024-08-01 17:29   ` [PATCH v4 1/3] buildtools: add helper to convert text file to header Stephen Hemminger
2024-08-02 15:15     ` Bruce Richardson
2024-08-01 17:29   ` [PATCH v4 2/3] test: remove unused resource API Stephen Hemminger
2024-08-02 15:16     ` Bruce Richardson
2024-08-01 17:29   ` [PATCH v4 3/3] test: restore cfgfile tests Stephen Hemminger
2024-08-02 15:21     ` Bruce Richardson
2024-08-02 16:44 ` [PATCH v5 0/4] restore unused " Stephen Hemminger
2024-08-02 16:45   ` [PATCH v5 1/4] buildtools: add helper to convert text file to header Stephen Hemminger
2024-08-02 16:45   ` [PATCH v5 2/4] test: remove unused resource API Stephen Hemminger
2024-08-02 16:45   ` [PATCH v5 3/4] test: restore cfgfile tests Stephen Hemminger
2024-08-02 16:52     ` Bruce Richardson
2024-08-02 16:45   ` [PATCH v5 4/4] test: rearrange test_cfgfiles cases Stephen Hemminger
2024-08-02 16:51     ` Bruce Richardson
2024-08-02 17:06       ` Stephen Hemminger
2024-08-06  8:37         ` Bruce Richardson
2024-08-13 15:57 ` [PATCH v6 0/4] test: restore cfgfile lib tests Stephen Hemminger
2024-08-13 15:57   ` [PATCH v6 1/4] buildtools: add helper to convert text file to header Stephen Hemminger
2024-08-13 15:57   ` [PATCH v6 2/4] test: remove unused resource API Stephen Hemminger
2024-08-13 15:57   ` [PATCH v6 3/4] test: rearrange test_cfgfiles cases Stephen Hemminger
2024-08-13 15:57   ` [PATCH v6 4/4] test: restore cfgfile tests Stephen Hemminger
2024-11-19 21:53   ` [PATCH v6 0/4] test: restore cfgfile lib tests Thomas Monjalon

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).