diff options
author | Alex Waterman <alexw@nvidia.com> | 2018-06-27 17:45:07 -0400 |
---|---|---|
committer | mobile promotions <svcmobile_promotions@nvidia.com> | 2018-08-10 02:11:06 -0400 |
commit | 691bf904451bfe2e4c44ea05319149996abbbbf1 (patch) | |
tree | 0fe66bd37989f9d619234b7f4d2be1df6ed61c85 | |
parent | 6e746a97cc7ee2bc5a3adee04dd9c65b3921eee5 (diff) |
gpu: nvgpu: unit: Add unit testing FW
Full documentation for this is in the unit testing
confluence page.
JIRA NVGPU-525
Bug 2261555
Change-Id: I463e6267eb0eb12b7313f8b275266e8faabe5ccf
Signed-off-by: Alex Waterman <alexw@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/1683915
GVS: Gerrit_Virtual_Submit
Reviewed-by: Konsta Holtta <kholtta@nvidia.com>
Reviewed-by: Terje Bergstrom <tbergstrom@nvidia.com>
Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com>
Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
-rw-r--r-- | userspace/Makefile | 95 | ||||
-rw-r--r-- | userspace/Makefile.sources | 16 | ||||
-rw-r--r-- | userspace/include/unit/args.h | 58 | ||||
-rw-r--r-- | userspace/include/unit/core.h | 63 | ||||
-rw-r--r-- | userspace/include/unit/io.h | 88 | ||||
-rw-r--r-- | userspace/include/unit/module.h | 31 | ||||
-rw-r--r-- | userspace/include/unit/results.h | 70 | ||||
-rw-r--r-- | userspace/include/unit/unit.h | 100 | ||||
-rw-r--r-- | userspace/src/args.c | 134 | ||||
-rw-r--r-- | userspace/src/exec.c | 90 | ||||
-rw-r--r-- | userspace/src/io.c | 105 | ||||
-rw-r--r-- | userspace/src/module.c | 167 | ||||
-rw-r--r-- | userspace/src/nvgpu.c | 78 | ||||
-rw-r--r-- | userspace/src/results.c | 128 | ||||
-rw-r--r-- | userspace/src/unit_main.c | 76 | ||||
-rwxr-xr-x | userspace/unit.sh | 16 | ||||
-rw-r--r-- | userspace/units/Makefile.units | 45 |
17 files changed, 1343 insertions, 17 deletions
diff --git a/userspace/Makefile b/userspace/Makefile index 70e93bad..56709ec4 100644 --- a/userspace/Makefile +++ b/userspace/Makefile | |||
@@ -18,6 +18,10 @@ | |||
18 | # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | 18 | # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER |
19 | # DEALINGS IN THE SOFTWARE. | 19 | # DEALINGS IN THE SOFTWARE. |
20 | 20 | ||
21 | # TODO: | ||
22 | # - Separate rule for nvgpu_unit shared library | ||
23 | # - Proper header dependency checking. | ||
24 | |||
21 | # Turn off suffix rules. They are deprecated. | 25 | # Turn off suffix rules. They are deprecated. |
22 | .SUFFIXES: | 26 | .SUFFIXES: |
23 | 27 | ||
@@ -28,25 +32,35 @@ TWD=$(CURDIR) | |||
28 | # Top level out dir. | 32 | # Top level out dir. |
29 | OUT=$(TWD)/build | 33 | OUT=$(TWD)/build |
30 | 34 | ||
35 | # Core unit test framework. | ||
36 | CORE_SRC=$(TWD)/src | ||
37 | CORE_OUT=$(OUT)/nvgpu_unit_core | ||
38 | |||
31 | # Nvgpu driver code. | 39 | # Nvgpu driver code. |
32 | NVGPU_SRC=$(TWD)/../drivers/gpu/nvgpu | 40 | NVGPU_SRC=$(TWD)/../drivers/gpu/nvgpu |
33 | NVGPU_OUT=$(OUT)/libnvgpu | 41 | NVGPU_OUT=$(OUT)/libnvgpu |
34 | 42 | ||
35 | INCLUDES= \ | 43 | # Unit tests themselves. |
36 | -I$(NVGPU_SRC) \ | 44 | UNIT_SRC=$(TWD)/units |
37 | -I$(NVGPU_SRC)/include \ | 45 | UNIT_OUT=$(OUT)/units |
38 | -I../include \ | ||
39 | -I../include/uapi | ||
40 | 46 | ||
41 | CONFIGS= \ | 47 | INCLUDES= \ |
42 | -D__NVGPU_POSIX__ | 48 | -I$(NVGPU_SRC) \ |
49 | -I$(NVGPU_SRC)/include \ | ||
50 | -I$(TWD)/../include \ | ||
51 | -I$(TWD)/../include/uapi \ | ||
52 | -I$(TWD)/include | ||
53 | |||
54 | CONFIGS=-D__NVGPU_POSIX__ | ||
43 | 55 | ||
44 | # Compiler, c-flags, etc. | 56 | # Compiler, c-flags, etc. |
45 | 57 | ||
46 | # CC = clang | 58 | # CC = clang |
47 | CC = gcc | 59 | CC = gcc |
48 | CFLAGS = -Wall -ggdb -Werror -fPIC $(INCLUDES) $(CONFIGS) | 60 | CFLAGS = -Wall -ggdb -Werror -fPIC $(INCLUDES) $(CONFIGS) |
49 | LIBS = -lpthread -pthread | 61 | LIB_PATHS = -L$(OUT) |
62 | LIBS = -lpthread -pthread -lgcov -ldl | ||
63 | |||
50 | 64 | ||
51 | # Source files. We expect $(OBJS) and $(HEADERS) to get filled in here. | 65 | # Source files. We expect $(OBJS) and $(HEADERS) to get filled in here. |
52 | include Makefile.sources | 66 | include Makefile.sources |
@@ -55,19 +69,68 @@ include Makefile.sources | |||
55 | # Linux kernel. | 69 | # Linux kernel. |
56 | include Makefile.configs | 70 | include Makefile.configs |
57 | 71 | ||
58 | all: $(OUT)/libnvgpu-drv.so | 72 | all: $(OUT)/nvgpu_unit $(UNITS) |
73 | |||
74 | # Convenience targets. | ||
75 | .PHONY: libnvgpu core units | ||
76 | libnvgpu: $(OUT)/libnvgpu-drv.so | ||
77 | core: $(OUT)/nvgpu_unit | ||
78 | units: $(UNITS) | ||
79 | |||
80 | # Note the weird libnvgpu_unit.so file: this is a bit of a hack. It lets the | ||
81 | # unit tests link back against the nvgpu_unit executable so that they can call | ||
82 | # functions (like unit_info()) directly. This shared library isn't actually | ||
83 | # used for anything beyond that. | ||
84 | # | ||
85 | # Also it really should have its own rule... | ||
86 | $(OUT)/nvgpu_unit: $(OUT)/libnvgpu-drv.so $(CORE_OBJS) | ||
87 | $(CC) -shared -o $(OUT)/libnvgpu_unit.so \ | ||
88 | $(CORE_OBJS) $(LIB_PATHS) $(LIBS) | ||
89 | $(CC) --coverage \ | ||
90 | -o $(OUT)/nvgpu_unit $(CORE_OBJS) $(LIB_PATHS) $(LIBS) | ||
59 | 91 | ||
60 | $(OUT)/libnvgpu-drv.so: $(OBJS) | 92 | $(OUT)/libnvgpu-drv.so: $(OBJS) |
61 | $(CC) -shared -o $(OUT)/libnvgpu-drv.so $(OBJS) -lgcov | 93 | $(CC) -shared -o $(OUT)/libnvgpu-drv.so $(OBJS) -lgcov |
62 | 94 | ||
63 | # Default build target for all the object files we want to build in userspace. | 95 | # Default build target for all the nvgpu driver object files we want to build in |
96 | # userspace. These get bundled into libnvgpu-drv.so. | ||
64 | $(NVGPU_OUT)/%.o : $(NVGPU_SRC)/%.c $(HEADERS) | 97 | $(NVGPU_OUT)/%.o : $(NVGPU_SRC)/%.c $(HEADERS) |
65 | @if [ ! -d $(dir $@) ] ; then \ | 98 | @if [ ! -d $(dir $@) ] ; then \ |
66 | mkdir -p $(dir $@) ; \ | 99 | mkdir -p $(dir $@) ; \ |
67 | fi | 100 | fi |
68 | $(CC) $(CFLAGS) $(configs) -c -o $@ $< | 101 | $(CC) --coverage $(CFLAGS) $(configs) -c -o $@ $< |
102 | |||
103 | # Build target for unit test files. These are not part of the libnvgpu-drv.so. | ||
104 | # These comprise the unit test framework. | ||
105 | $(CORE_OUT)/%.o : $(CORE_SRC)/%.c $(CORE_HEADERS) | ||
106 | @if [ ! -d $(dir $@) ] ; then \ | ||
107 | mkdir -p $(dir $@) ; \ | ||
108 | fi | ||
109 | $(CC) --coverage $(CFLAGS) $(configs) -c -o $@ $< | ||
110 | |||
111 | # Certain variables should be exported to the unit test module builds. | ||
112 | export TWD INCLUDES CONFIGS UNIT_SRC UNIT_OUT | ||
113 | export CC CFLAGS LIB_PATHS LIBS | ||
69 | 114 | ||
70 | .PHONY: clean | 115 | .PHONY: $(UNITS) |
116 | $(UNITS): $(OUT)/libnvgpu-drv.so | ||
117 | @echo "Building unit module: $@" | ||
118 | @+$(MAKE) --no-print-directory -C $@ | ||
71 | 119 | ||
72 | clean: | 120 | .PHONY: clean nvgpu_clean core_clean unit_clean |
121 | |||
122 | clean: nvgpu_clean core_clean unit_clean | ||
73 | rm -rf $(OUT) | 123 | rm -rf $(OUT) |
124 | |||
125 | nvgpu_clean: | ||
126 | rm -rf $(OUT)/libnvgpu* | ||
127 | |||
128 | core_clean: | ||
129 | rm -rf $(OUT)/nvgpu_unit* | ||
130 | |||
131 | unit_clean: | ||
132 | @for d in $(UNITS); do \ | ||
133 | echo Cleaning $$d; \ | ||
134 | $(MAKE) --no-print-directory -C $$d clean; \ | ||
135 | done | ||
136 | rm -rf $(OUT)/units | ||
diff --git a/userspace/Makefile.sources b/userspace/Makefile.sources index 3598c971..cb46573a 100644 --- a/userspace/Makefile.sources +++ b/userspace/Makefile.sources | |||
@@ -24,7 +24,6 @@ include ../drivers/gpu/nvgpu/Makefile.sources | |||
24 | 24 | ||
25 | OBJS := $(srcs:%.c=$(NVGPU_OUT)/%.o) | 25 | OBJS := $(srcs:%.c=$(NVGPU_OUT)/%.o) |
26 | 26 | ||
27 | |||
28 | HEADERS := \ | 27 | HEADERS := \ |
29 | $(NVGPU_SRC)/include/nvgpu/*.h \ | 28 | $(NVGPU_SRC)/include/nvgpu/*.h \ |
30 | $(NVGPU_SRC)/include/nvgpu/hw/*/*.h \ | 29 | $(NVGPU_SRC)/include/nvgpu/hw/*/*.h \ |
@@ -32,3 +31,18 @@ HEADERS := \ | |||
32 | $(NVGPU_SRC)/gm20b/*.h \ | 31 | $(NVGPU_SRC)/gm20b/*.h \ |
33 | $(NVGPU_SRC)/gp10b/*.h \ | 32 | $(NVGPU_SRC)/gp10b/*.h \ |
34 | $(NVGPU_SRC)/gv11b/*.h | 33 | $(NVGPU_SRC)/gv11b/*.h |
34 | |||
35 | CORE_OBJS := \ | ||
36 | $(CORE_OUT)/unit_main.o \ | ||
37 | $(CORE_OUT)/nvgpu.o \ | ||
38 | $(CORE_OUT)/args.o \ | ||
39 | $(CORE_OUT)/io.o \ | ||
40 | $(CORE_OUT)/module.o \ | ||
41 | $(CORE_OUT)/results.o \ | ||
42 | $(CORE_OUT)/exec.o | ||
43 | |||
44 | CORE_HEADERS := \ | ||
45 | $(CORE_SRC)/../include/unit/*.h | ||
46 | |||
47 | # Each directory under the UNIT_SRC directory should correspond to one module. | ||
48 | UNITS := | ||
diff --git a/userspace/include/unit/args.h b/userspace/include/unit/args.h new file mode 100644 index 00000000..def84a29 --- /dev/null +++ b/userspace/include/unit/args.h | |||
@@ -0,0 +1,58 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved. | ||
3 | * | ||
4 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
5 | * copy of this software and associated documentation files (the "Software"), | ||
6 | * to deal in the Software without restriction, including without limitation | ||
7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
8 | * and/or sell copies of the Software, and to permit persons to whom the | ||
9 | * Software is furnished to do so, subject to the following conditions: | ||
10 | * | ||
11 | * The above copyright notice and this permission notice shall be included in | ||
12 | * all copies or substantial portions of the Software. | ||
13 | * | ||
14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
17 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | ||
19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | ||
20 | * DEALINGS IN THE SOFTWARE. | ||
21 | */ | ||
22 | |||
23 | #ifndef __UNIT_ARGS_H__ | ||
24 | #define __UNIT_ARGS_H__ | ||
25 | |||
26 | #include <stdbool.h> | ||
27 | |||
28 | /* | ||
29 | * Allow defaults to be changed at compile time. | ||
30 | */ | ||
31 | #define __stringify(x) #x | ||
32 | #define stringify(x) __stringify(x) | ||
33 | |||
34 | #ifndef __DEFAULT_ARG_UNIT_LOAD_PATH | ||
35 | #define __DEFAULT_ARG_UNIT_LOAD_PATH build/units | ||
36 | #endif | ||
37 | #define DEFAULT_ARG_UNIT_LOAD_PATH stringify(__DEFAULT_ARG_UNIT_LOAD_PATH) | ||
38 | |||
39 | struct unit_fw; | ||
40 | |||
41 | struct unit_fw_args { | ||
42 | bool help; | ||
43 | int verbose_lvl; | ||
44 | bool no_color; | ||
45 | |||
46 | const char *unit_name; | ||
47 | const char *unit_load_path; | ||
48 | }; | ||
49 | |||
50 | int core_parse_args(struct unit_fw *fw, int argc, char **argv); | ||
51 | void core_print_help(struct unit_fw *fw); | ||
52 | |||
53 | /* | ||
54 | * Convenience for getting the args struct pointer. | ||
55 | */ | ||
56 | #define args(fw) ((fw)->args) | ||
57 | |||
58 | #endif | ||
diff --git a/userspace/include/unit/core.h b/userspace/include/unit/core.h new file mode 100644 index 00000000..d9d119db --- /dev/null +++ b/userspace/include/unit/core.h | |||
@@ -0,0 +1,63 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved. | ||
3 | * | ||
4 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
5 | * copy of this software and associated documentation files (the "Software"), | ||
6 | * to deal in the Software without restriction, including without limitation | ||
7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
8 | * and/or sell copies of the Software, and to permit persons to whom the | ||
9 | * Software is furnished to do so, subject to the following conditions: | ||
10 | * | ||
11 | * The above copyright notice and this permission notice shall be included in | ||
12 | * all copies or substantial portions of the Software. | ||
13 | * | ||
14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
17 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | ||
19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | ||
20 | * DEALINGS IN THE SOFTWARE. | ||
21 | */ | ||
22 | |||
23 | #ifndef __UNIT_CORE_H__ | ||
24 | #define __UNIT_CORE_H__ | ||
25 | |||
26 | struct unit_fw_args; | ||
27 | struct unit_modules; | ||
28 | struct unit_results; | ||
29 | |||
30 | struct gk20a; | ||
31 | |||
32 | /* | ||
33 | * The core unit testing framework data structure. Keeps track of global state | ||
34 | * for the unit test app. | ||
35 | */ | ||
36 | struct unit_fw { | ||
37 | struct unit_fw_args *args; | ||
38 | |||
39 | struct unit_module **modules; | ||
40 | |||
41 | struct unit_results *results; | ||
42 | |||
43 | /* | ||
44 | * nvgpu-drv interface. Currently the only two directly referenced | ||
45 | * functions are: | ||
46 | * | ||
47 | * nvgpu_posix_probe() | ||
48 | * nvgpu_posix_cleanup() | ||
49 | * | ||
50 | * There will get populated so that we can call them before/after each | ||
51 | * module. | ||
52 | */ | ||
53 | void *nvgpu_so; | ||
54 | struct { | ||
55 | struct gk20a *(*nvgpu_posix_probe)(void); | ||
56 | void (*nvgpu_posix_cleanup)(struct gk20a *g); | ||
57 | } nvgpu; | ||
58 | }; | ||
59 | |||
60 | int core_load_nvgpu(struct unit_fw *fw); | ||
61 | int core_exec(struct unit_fw *fw); | ||
62 | |||
63 | #endif | ||
diff --git a/userspace/include/unit/io.h b/userspace/include/unit/io.h new file mode 100644 index 00000000..1fd0fa43 --- /dev/null +++ b/userspace/include/unit/io.h | |||
@@ -0,0 +1,88 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved. | ||
3 | * | ||
4 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
5 | * copy of this software and associated documentation files (the "Software"), | ||
6 | * to deal in the Software without restriction, including without limitation | ||
7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
8 | * and/or sell copies of the Software, and to permit persons to whom the | ||
9 | * Software is furnished to do so, subject to the following conditions: | ||
10 | * | ||
11 | * The above copyright notice and this permission notice shall be included in | ||
12 | * all copies or substantial portions of the Software. | ||
13 | * | ||
14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
17 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | ||
19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | ||
20 | * DEALINGS IN THE SOFTWARE. | ||
21 | */ | ||
22 | |||
23 | #ifndef __UNIT_IO_H__ | ||
24 | #define __UNIT_IO_H__ | ||
25 | |||
26 | struct unit_fw; | ||
27 | struct unit_module; | ||
28 | |||
29 | /* | ||
30 | * necessary for args(fw) macro. IO will always, in general, depend on args | ||
31 | * since the args will specify where IO should be directed to. | ||
32 | */ | ||
33 | #include <unit/args.h> | ||
34 | |||
35 | #define core_msg(fw, msg, ...) \ | ||
36 | core_vbs(fw, 0, msg, ##__VA_ARGS__) | ||
37 | #define core_msg_color(fw, color, msg, ...) \ | ||
38 | core_vbs_color(fw, color, 0, msg, ##__VA_ARGS__) | ||
39 | |||
40 | #define core_vbs_color(fw, color, lvl, msg, ...) \ | ||
41 | do { \ | ||
42 | if ((lvl) > args(fw)->verbose_lvl) \ | ||
43 | continue; \ | ||
44 | \ | ||
45 | /* Print if verbosity level is high enough. */ \ | ||
46 | __core_print_stdout(fw, color, msg, ##__VA_ARGS__); \ | ||
47 | } while (0) | ||
48 | #define core_vbs(fw, lvl, msg, ...) \ | ||
49 | core_vbs_color(fw, NULL, lvl, msg, ##__VA_ARGS__) | ||
50 | |||
51 | #define core_err(fw, msg, ...) \ | ||
52 | __core_print_stderr(fw, "(%s:%d) " msg, \ | ||
53 | __func__, __LINE__, ##__VA_ARGS__) | ||
54 | |||
55 | /* | ||
56 | * Output macro for unit tests to use. | ||
57 | */ | ||
58 | #define unit_info(unit, msg, ...) \ | ||
59 | __unit_info_color(unit, NULL, msg, ##__VA_ARGS__) | ||
60 | #define unit_err(unit, msg, ...) \ | ||
61 | __unit_info_color(unit, C_RED, msg, ##__VA_ARGS__) | ||
62 | |||
63 | /* | ||
64 | * Don't go overboard with these!!! | ||
65 | */ | ||
66 | #define C_RED "\x1B[31m" | ||
67 | #define C_GREEN "\x1B[32m" | ||
68 | #define C_YELLOW "\x1B[33m" | ||
69 | #define C_BLUE "\x1B[34m" | ||
70 | #define C_MAGENTA "\x1B[35m" | ||
71 | #define C_CYAN "\x1B[36m" | ||
72 | #define C_WHITE "\x1B[37m" | ||
73 | #define C_RESET "\x1B[0m" | ||
74 | |||
75 | /* | ||
76 | * Printing functions. Do not use these directly. Instead use the provided | ||
77 | * macros. | ||
78 | */ | ||
79 | __attribute__((format (printf, 3, 4))) | ||
80 | void __core_print_stdout(struct unit_fw *fw, const char *color, | ||
81 | const char *fmt, ...); | ||
82 | __attribute__((format (printf, 2, 3))) | ||
83 | void __core_print_stderr(struct unit_fw *fw, const char *fmt, ...); | ||
84 | __attribute__((format (printf, 3, 4))) | ||
85 | void __unit_info_color(struct unit_module *unit, const char *color, | ||
86 | const char *fmt, ...); | ||
87 | |||
88 | #endif | ||
diff --git a/userspace/include/unit/module.h b/userspace/include/unit/module.h new file mode 100644 index 00000000..79737d61 --- /dev/null +++ b/userspace/include/unit/module.h | |||
@@ -0,0 +1,31 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved. | ||
3 | * | ||
4 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
5 | * copy of this software and associated documentation files (the "Software"), | ||
6 | * to deal in the Software without restriction, including without limitation | ||
7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
8 | * and/or sell copies of the Software, and to permit persons to whom the | ||
9 | * Software is furnished to do so, subject to the following conditions: | ||
10 | * | ||
11 | * The above copyright notice and this permission notice shall be included in | ||
12 | * all copies or substantial portions of the Software. | ||
13 | * | ||
14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
17 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | ||
19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | ||
20 | * DEALINGS IN THE SOFTWARE. | ||
21 | */ | ||
22 | |||
23 | #ifndef __UNIT_MODULE_H__ | ||
24 | #define __UNIT_MODULE_H__ | ||
25 | |||
26 | struct unit_fw; | ||
27 | struct unit_module; | ||
28 | |||
29 | struct unit_module **core_load_modules(struct unit_fw *fw); | ||
30 | |||
31 | #endif | ||
diff --git a/userspace/include/unit/results.h b/userspace/include/unit/results.h new file mode 100644 index 00000000..fb88e59d --- /dev/null +++ b/userspace/include/unit/results.h | |||
@@ -0,0 +1,70 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved. | ||
3 | * | ||
4 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
5 | * copy of this software and associated documentation files (the "Software"), | ||
6 | * to deal in the Software without restriction, including without limitation | ||
7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
8 | * and/or sell copies of the Software, and to permit persons to whom the | ||
9 | * Software is furnished to do so, subject to the following conditions: | ||
10 | * | ||
11 | * The above copyright notice and this permission notice shall be included in | ||
12 | * all copies or substantial portions of the Software. | ||
13 | * | ||
14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
17 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | ||
19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | ||
20 | * DEALINGS IN THE SOFTWARE. | ||
21 | */ | ||
22 | |||
23 | #ifndef __UNIT_RESULTS_H__ | ||
24 | #define __UNIT_RESULTS_H__ | ||
25 | |||
26 | /* | ||
27 | * Keep track of the the results of a set of unit tests. This is effectively | ||
28 | * just a single linked list of records for each test. | ||
29 | */ | ||
30 | |||
31 | struct unit_test_record { | ||
32 | /* | ||
33 | * Let's us determine the name of the test. | ||
34 | */ | ||
35 | struct unit_module *mod; | ||
36 | struct unit_module_test *test; | ||
37 | |||
38 | /* | ||
39 | * True for pass, false for fail. | ||
40 | */ | ||
41 | bool status; | ||
42 | |||
43 | struct unit_test_record *next; | ||
44 | }; | ||
45 | |||
46 | struct unit_test_list { | ||
47 | struct unit_test_record *head; | ||
48 | struct unit_test_record *last; | ||
49 | }; | ||
50 | |||
51 | struct unit_results { | ||
52 | struct unit_test_list passing; | ||
53 | struct unit_test_list failing; | ||
54 | |||
55 | int nr_tests; | ||
56 | int nr_passing; | ||
57 | }; | ||
58 | |||
59 | #define for_record_in_test_list(__test_list, __test) \ | ||
60 | for ((__test) = (__test_list)->head; \ | ||
61 | (__test) != NULL; \ | ||
62 | (__test) = (__test)->next) | ||
63 | |||
64 | int core_add_test_record(struct unit_fw *fw, | ||
65 | struct unit_module *mod, | ||
66 | struct unit_module_test *test, | ||
67 | bool success); | ||
68 | void core_print_test_status(struct unit_fw *fw); | ||
69 | |||
70 | #endif | ||
diff --git a/userspace/include/unit/unit.h b/userspace/include/unit/unit.h new file mode 100644 index 00000000..9438d4d9 --- /dev/null +++ b/userspace/include/unit/unit.h | |||
@@ -0,0 +1,100 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved. | ||
3 | * | ||
4 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
5 | * copy of this software and associated documentation files (the "Software"), | ||
6 | * to deal in the Software without restriction, including without limitation | ||
7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
8 | * and/or sell copies of the Software, and to permit persons to whom the | ||
9 | * Software is furnished to do so, subject to the following conditions: | ||
10 | * | ||
11 | * The above copyright notice and this permission notice shall be included in | ||
12 | * all copies or substantial portions of the Software. | ||
13 | * | ||
14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
17 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | ||
19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | ||
20 | * DEALINGS IN THE SOFTWARE. | ||
21 | */ | ||
22 | |||
23 | #ifndef __UNIT_UNIT_H__ | ||
24 | #define __UNIT_UNIT_H__ | ||
25 | |||
26 | struct gk20a; | ||
27 | |||
28 | struct unit_module; | ||
29 | typedef int (*module_test_fn)(struct unit_module *m, | ||
30 | struct gk20a *g, void *args); | ||
31 | |||
32 | #define UNIT_SUCCESS 0 | ||
33 | #define UNIT_FAIL -1 | ||
34 | |||
35 | struct unit_module_test { | ||
36 | /* | ||
37 | * Name of the test. | ||
38 | */ | ||
39 | const char *name; | ||
40 | |||
41 | /* | ||
42 | * Function to call to execute the test. | ||
43 | */ | ||
44 | module_test_fn fn; | ||
45 | |||
46 | /* | ||
47 | * A void pointer to arbitrary arguments. Lets the same unit test | ||
48 | * function perform multiple tests. This gets passed into the | ||
49 | * module_test_fn as @args. | ||
50 | */ | ||
51 | void *args; | ||
52 | }; | ||
53 | |||
54 | /* | ||
55 | * Interface to the unit test framework module loader. Each unit test module | ||
56 | * will have exactly one of these. | ||
57 | */ | ||
58 | struct unit_module { | ||
59 | /* | ||
60 | * Name of the module. | ||
61 | */ | ||
62 | const char *name; | ||
63 | |||
64 | /* | ||
65 | * NULL terminated list of tests within the module. | ||
66 | */ | ||
67 | struct unit_module_test *tests; | ||
68 | unsigned long nr_tests; | ||
69 | |||
70 | /* | ||
71 | * For the core FW to use. Not for modules!!! | ||
72 | */ | ||
73 | void *lib_handle; | ||
74 | struct unit_fw *fw; | ||
75 | }; | ||
76 | |||
77 | #define UNIT_MODULE(__name, __tests) \ | ||
78 | struct unit_module __unit_module__ = { \ | ||
79 | .name = #__name, \ | ||
80 | .tests = __tests, \ | ||
81 | .nr_tests = (sizeof(__tests) / \ | ||
82 | sizeof(struct unit_module_test)), \ | ||
83 | .lib_handle = NULL, \ | ||
84 | } | ||
85 | |||
86 | #define UNIT_TEST(__name, __fn, __args) \ | ||
87 | { \ | ||
88 | .name = #__name, \ | ||
89 | .fn = __fn, \ | ||
90 | .args = __args, \ | ||
91 | } | ||
92 | |||
93 | #define unit_return_fail(m, msg, ...) \ | ||
94 | do { \ | ||
95 | unit_err(m, "%s():%d " msg, \ | ||
96 | __func__, __LINE__, ##__VA_ARGS__); \ | ||
97 | return UNIT_FAIL; \ | ||
98 | } while (0) | ||
99 | |||
100 | #endif | ||
diff --git a/userspace/src/args.c b/userspace/src/args.c new file mode 100644 index 00000000..d91c6f6e --- /dev/null +++ b/userspace/src/args.c | |||
@@ -0,0 +1,134 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved. | ||
3 | * | ||
4 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
5 | * copy of this software and associated documentation files (the "Software"), | ||
6 | * to deal in the Software without restriction, including without limitation | ||
7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
8 | * and/or sell copies of the Software, and to permit persons to whom the | ||
9 | * Software is furnished to do so, subject to the following conditions: | ||
10 | * | ||
11 | * The above copyright notice and this permission notice shall be included in | ||
12 | * all copies or substantial portions of the Software. | ||
13 | * | ||
14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
17 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | ||
19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | ||
20 | * DEALINGS IN THE SOFTWARE. | ||
21 | */ | ||
22 | |||
23 | #include <stdio.h> | ||
24 | #include <getopt.h> | ||
25 | #include <stdlib.h> | ||
26 | #include <string.h> | ||
27 | |||
28 | #include <unit/core.h> | ||
29 | #include <unit/args.h> | ||
30 | #include <unit/io.h> | ||
31 | |||
32 | static struct option core_opts[] = { | ||
33 | { "help", 0, NULL, 'h' }, | ||
34 | { "verbose", 0, NULL, 'v' }, | ||
35 | { "quiet", 0, NULL, 'q' }, | ||
36 | { "no-color", 0, NULL, 'C' }, | ||
37 | |||
38 | { "unit-load-path", 1, NULL, 'L' }, | ||
39 | |||
40 | { NULL, 0, NULL, 0 } | ||
41 | }; | ||
42 | |||
43 | static const char *core_opts_str = "hvqCL:"; | ||
44 | |||
45 | void core_print_help(struct unit_fw *fw) | ||
46 | { | ||
47 | const char **line, *help_msg[] = { | ||
48 | "NvGpu Unit Testing FW. Basic usage\n", | ||
49 | "\n", | ||
50 | " $ nvgpu_unit [options] <unit>\n", | ||
51 | "\n", | ||
52 | "Basic usage consists of one or more options and a particular unit test to\n", | ||
53 | "execute.\n", | ||
54 | "\n", | ||
55 | "Available options are as follows:\n", | ||
56 | "\n", | ||
57 | " -h, --help Print this help message and exit.\n", | ||
58 | " -v, --verbose Increment the verbosity level. Can be specified\n", | ||
59 | " multiple times.\n", | ||
60 | " -q, --quiet Set the verbose level back to 0.\n", | ||
61 | " -C, --no-color Disable color printing; for example, if writing\n", | ||
62 | " output to a file the color escape sequences will\n", | ||
63 | " corrupt that file.\n", | ||
64 | " -L, --unit-load-path <PATH>\n", | ||
65 | " Path to where the unit test libraries reside.\n", | ||
66 | "\n", | ||
67 | "Note: mandatory arguments to long arguments are mandatory for short\n", | ||
68 | "arguments as well.\n", | ||
69 | NULL | ||
70 | }; | ||
71 | |||
72 | line = help_msg; | ||
73 | while (*line != NULL) { | ||
74 | core_msg(fw, "%s", *line); | ||
75 | line++; | ||
76 | } | ||
77 | } | ||
78 | |||
79 | static void set_arg_defaults(struct unit_fw_args *args) | ||
80 | { | ||
81 | args->unit_load_path = DEFAULT_ARG_UNIT_LOAD_PATH; | ||
82 | } | ||
83 | |||
84 | /* | ||
85 | * Parse command line arguments. | ||
86 | */ | ||
87 | int core_parse_args(struct unit_fw *fw, int argc, char **argv) | ||
88 | { | ||
89 | int c, opt_index; | ||
90 | struct unit_fw_args *args; | ||
91 | |||
92 | args = malloc(sizeof(*args)); | ||
93 | if (!args) | ||
94 | return -1; | ||
95 | |||
96 | memset(args, 0, sizeof(*args)); | ||
97 | set_arg_defaults(args); | ||
98 | |||
99 | fw->args = args; | ||
100 | |||
101 | while (1) { | ||
102 | c = getopt_long(argc, argv, | ||
103 | core_opts_str, core_opts, &opt_index); | ||
104 | |||
105 | if (c == -1) | ||
106 | break; | ||
107 | |||
108 | switch (c) { | ||
109 | case 'h': | ||
110 | args->help = true; | ||
111 | break; | ||
112 | case 'v': | ||
113 | args->verbose_lvl += 1; | ||
114 | break; | ||
115 | case 'q': | ||
116 | args->verbose_lvl = 0; | ||
117 | break; | ||
118 | case 'C': | ||
119 | args->no_color = true; | ||
120 | break; | ||
121 | case 'L': | ||
122 | args->unit_load_path = optarg; | ||
123 | break; | ||
124 | case '?': | ||
125 | args->help = true; | ||
126 | return -1; | ||
127 | default: | ||
128 | core_err(fw, "bug?!\n"); | ||
129 | return -1; | ||
130 | } | ||
131 | } | ||
132 | |||
133 | return 0; | ||
134 | } | ||
diff --git a/userspace/src/exec.c b/userspace/src/exec.c new file mode 100644 index 00000000..b9ba1336 --- /dev/null +++ b/userspace/src/exec.c | |||
@@ -0,0 +1,90 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved. | ||
3 | * | ||
4 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
5 | * copy of this software and associated documentation files (the "Software"), | ||
6 | * to deal in the Software without restriction, including without limitation | ||
7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
8 | * and/or sell copies of the Software, and to permit persons to whom the | ||
9 | * Software is furnished to do so, subject to the following conditions: | ||
10 | * | ||
11 | * The above copyright notice and this permission notice shall be included in | ||
12 | * all copies or substantial portions of the Software. | ||
13 | * | ||
14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
17 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | ||
19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | ||
20 | * DEALINGS IN THE SOFTWARE. | ||
21 | */ | ||
22 | |||
23 | #include <stdlib.h> | ||
24 | |||
25 | #include <unit/io.h> | ||
26 | #include <unit/core.h> | ||
27 | #include <unit/unit.h> | ||
28 | #include <unit/module.h> | ||
29 | #include <unit/results.h> | ||
30 | |||
31 | #include <nvgpu/posix/probe.h> | ||
32 | |||
33 | /* | ||
34 | * Execute a module and all its subtests. This function builds a gk20a for the | ||
35 | * test to use by executing nvgpu_posix_probe() and nvgpu_posix_cleanup(); | ||
36 | */ | ||
37 | static int core_exec_module(struct unit_fw *fw, | ||
38 | struct unit_module *module) | ||
39 | { | ||
40 | unsigned int i; | ||
41 | struct gk20a *g = fw->nvgpu.nvgpu_posix_probe(); | ||
42 | |||
43 | if (!g) | ||
44 | return -1; | ||
45 | |||
46 | core_vbs(fw, 1, "Execing module: %s\n", module->name); | ||
47 | |||
48 | /* | ||
49 | * Execute each test within the module. No reinit is done between tests. | ||
50 | * Thats up to the module itself to handle. Any setup/teardown between | ||
51 | * unit tests must be handled within the module. | ||
52 | */ | ||
53 | for (i = 0; i < module->nr_tests; i++) { | ||
54 | struct unit_module_test *t = module->tests + i; | ||
55 | int test_status; | ||
56 | |||
57 | core_msg(fw, "Running %s.%s\n", module->name, t->name); | ||
58 | test_status = t->fn(module, g, t->args); | ||
59 | |||
60 | if (test_status != UNIT_SUCCESS) | ||
61 | core_msg_color(fw, C_RED, | ||
62 | " Unit error! Test %s.%s FAILED!\n", | ||
63 | module->name, t->name); | ||
64 | |||
65 | core_add_test_record(fw, module, t, | ||
66 | test_status == UNIT_SUCCESS); | ||
67 | } | ||
68 | |||
69 | fw->nvgpu.nvgpu_posix_cleanup(g); | ||
70 | |||
71 | return 0; | ||
72 | } | ||
73 | |||
74 | /* | ||
75 | * Execute all modules loaded by the unit test framework. | ||
76 | */ | ||
77 | int core_exec(struct unit_fw *fw) | ||
78 | { | ||
79 | int ret; | ||
80 | struct unit_module **modules; | ||
81 | |||
82 | for (modules = fw->modules; *modules != NULL; modules++) { | ||
83 | ret = core_exec_module(fw, *modules); | ||
84 | |||
85 | if (ret != 0) | ||
86 | return ret; | ||
87 | } | ||
88 | |||
89 | return 0; | ||
90 | } | ||
diff --git a/userspace/src/io.c b/userspace/src/io.c new file mode 100644 index 00000000..21ac54da --- /dev/null +++ b/userspace/src/io.c | |||
@@ -0,0 +1,105 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved. | ||
3 | * | ||
4 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
5 | * copy of this software and associated documentation files (the "Software"), | ||
6 | * to deal in the Software without restriction, including without limitation | ||
7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
8 | * and/or sell copies of the Software, and to permit persons to whom the | ||
9 | * Software is furnished to do so, subject to the following conditions: | ||
10 | * | ||
11 | * The above copyright notice and this permission notice shall be included in | ||
12 | * all copies or substantial portions of the Software. | ||
13 | * | ||
14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
17 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | ||
19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | ||
20 | * DEALINGS IN THE SOFTWARE. | ||
21 | */ | ||
22 | |||
23 | #include <stdio.h> | ||
24 | #include <stdarg.h> | ||
25 | #include <string.h> | ||
26 | |||
27 | #include <unit/io.h> | ||
28 | #include <unit/args.h> | ||
29 | #include <unit/core.h> | ||
30 | #include <unit/unit.h> | ||
31 | |||
32 | #define MAX_LOG_LINE_LENGTH 4096 | ||
33 | |||
34 | static void __core_print_file(struct unit_fw *fw, FILE *filp, | ||
35 | const char *prefix, const char *msg, | ||
36 | const char *color) | ||
37 | { | ||
38 | if (color == NULL || args(fw)->no_color) | ||
39 | color = ""; | ||
40 | |||
41 | fprintf(filp, "[%s%s%s] %s%s%s", | ||
42 | color, prefix, C_RESET, | ||
43 | color, msg, C_RESET); | ||
44 | } | ||
45 | |||
46 | __attribute__((format (printf, 3, 4))) | ||
47 | void __core_print_stdout(struct unit_fw *fw, const char *color, | ||
48 | const char *fmt, ...) | ||
49 | { | ||
50 | va_list args; | ||
51 | char buf[MAX_LOG_LINE_LENGTH]; | ||
52 | |||
53 | va_start(args, fmt); | ||
54 | vsnprintf(buf, MAX_LOG_LINE_LENGTH, fmt, args); | ||
55 | va_end(args); | ||
56 | |||
57 | buf[MAX_LOG_LINE_LENGTH - 1] = 0; | ||
58 | |||
59 | __core_print_file(fw, stdout, "C", buf, color); | ||
60 | } | ||
61 | |||
62 | __attribute__((format (printf, 2, 3))) | ||
63 | void __core_print_stderr(struct unit_fw *fw, const char *fmt, ...) | ||
64 | { | ||
65 | va_list args; | ||
66 | char buf[MAX_LOG_LINE_LENGTH]; | ||
67 | |||
68 | va_start(args, fmt); | ||
69 | vsnprintf(buf, MAX_LOG_LINE_LENGTH, fmt, args); | ||
70 | va_end(args); | ||
71 | |||
72 | buf[MAX_LOG_LINE_LENGTH - 1] = 0; | ||
73 | |||
74 | __core_print_file(fw, stdout, "E", buf, C_RED); | ||
75 | } | ||
76 | |||
77 | __attribute__((format (printf, 3, 4))) | ||
78 | void __unit_info_color(struct unit_module *unit, const char *color, | ||
79 | const char *fmt, ...) | ||
80 | { | ||
81 | va_list args; | ||
82 | char buf[MAX_LOG_LINE_LENGTH]; | ||
83 | char *msg_start; | ||
84 | int written; | ||
85 | |||
86 | /* | ||
87 | * Default color for module prints is blue. Users can still turn this | ||
88 | * off with '-C'. | ||
89 | */ | ||
90 | if (color == NULL) | ||
91 | color = C_BLUE; | ||
92 | |||
93 | /* | ||
94 | * First prepend the unit name to the print. | ||
95 | */ | ||
96 | written = snprintf(buf, MAX_LOG_LINE_LENGTH, " [%s] ", unit->name); | ||
97 | |||
98 | msg_start = buf + written; | ||
99 | |||
100 | va_start(args, fmt); | ||
101 | vsnprintf(msg_start, MAX_LOG_LINE_LENGTH - written, fmt, args); | ||
102 | va_end(args); | ||
103 | |||
104 | __core_print_file(unit->fw, stdout, "T", buf, color); | ||
105 | } | ||
diff --git a/userspace/src/module.c b/userspace/src/module.c new file mode 100644 index 00000000..c111c6cb --- /dev/null +++ b/userspace/src/module.c | |||
@@ -0,0 +1,167 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved. | ||
3 | * | ||
4 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
5 | * copy of this software and associated documentation files (the "Software"), | ||
6 | * to deal in the Software without restriction, including without limitation | ||
7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
8 | * and/or sell copies of the Software, and to permit persons to whom the | ||
9 | * Software is furnished to do so, subject to the following conditions: | ||
10 | * | ||
11 | * The above copyright notice and this permission notice shall be included in | ||
12 | * all copies or substantial portions of the Software. | ||
13 | * | ||
14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
17 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | ||
19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | ||
20 | * DEALINGS IN THE SOFTWARE. | ||
21 | */ | ||
22 | |||
23 | #include <errno.h> | ||
24 | #include <dlfcn.h> | ||
25 | #include <dirent.h> | ||
26 | #include <string.h> | ||
27 | #include <stdlib.h> | ||
28 | |||
29 | #include <sys/types.h> | ||
30 | |||
31 | #include <unit/core.h> | ||
32 | #include <unit/io.h> | ||
33 | #include <unit/args.h> | ||
34 | #include <unit/unit.h> | ||
35 | |||
36 | static int check_module(struct unit_fw *fw, struct unit_module *mod) | ||
37 | { | ||
38 | unsigned int i; | ||
39 | |||
40 | /* | ||
41 | * Make sure this module has reasonable data. | ||
42 | */ | ||
43 | if (mod->name == NULL) { | ||
44 | core_err(fw, "Unnamed module!"); | ||
45 | return -1; | ||
46 | } | ||
47 | |||
48 | if (mod->tests == NULL || mod->nr_tests == 0) { | ||
49 | core_err(fw, "%s: Empty module!\n", mod->name); | ||
50 | return -1; | ||
51 | } | ||
52 | |||
53 | for (i = 0; i < mod->nr_tests; i++) { | ||
54 | struct unit_module_test *test = &mod->tests[i]; | ||
55 | |||
56 | if (test->name == NULL) { | ||
57 | core_err(fw, "%s: Unnamed test\n", mod->name); | ||
58 | return -1; | ||
59 | } | ||
60 | |||
61 | if (test->fn == NULL) { | ||
62 | core_err(fw, "%s: Test %s missing function \n", | ||
63 | mod->name, test->name); | ||
64 | return -1; | ||
65 | } | ||
66 | } | ||
67 | |||
68 | return 0; | ||
69 | } | ||
70 | |||
71 | static struct unit_module *load_one_module(struct unit_fw *fw, | ||
72 | struct dirent *dent) | ||
73 | { | ||
74 | void *lib_handle; | ||
75 | struct unit_module *mod; | ||
76 | |||
77 | core_vbs(fw, 1, "Loading: %s\n", dent->d_name); | ||
78 | |||
79 | lib_handle = dlopen(dent->d_name, RTLD_NOW); | ||
80 | if (lib_handle == NULL) { | ||
81 | core_err(fw, "Failed to load %s: %s\n", | ||
82 | dent->d_name, dlerror()); | ||
83 | return NULL; | ||
84 | } | ||
85 | |||
86 | mod = dlsym(lib_handle, "__unit_module__"); | ||
87 | if (mod == NULL) { | ||
88 | core_vbs(fw, 1, | ||
89 | "Failed to resolve __unit_module__ in %s: %s\n", | ||
90 | dent->d_name, dlerror()); | ||
91 | return NULL; | ||
92 | } | ||
93 | |||
94 | mod->lib_handle = lib_handle; | ||
95 | mod->fw = fw; | ||
96 | |||
97 | core_vbs(fw, 1, " '%s' contains %lu tests\n", mod->name, mod->nr_tests); | ||
98 | |||
99 | return mod; | ||
100 | } | ||
101 | |||
102 | /* | ||
103 | * Load all the modules we can from the module load path. Return the list of | ||
104 | * loaded module as an array of pointers to modules. The returned list of | ||
105 | * modules is NULL terminated. | ||
106 | */ | ||
107 | struct unit_module **core_load_modules(struct unit_fw *fw) | ||
108 | { | ||
109 | int nr_modules = 0, i; | ||
110 | DIR *load_dir; | ||
111 | struct dirent *ent; | ||
112 | const char *load_path = args(fw)->unit_load_path; | ||
113 | struct unit_module **modules, *mod; | ||
114 | |||
115 | core_vbs(fw, 1, "Loading modules from %s\n", load_path); | ||
116 | |||
117 | /* | ||
118 | * Open and count the number of files in the dir. | ||
119 | */ | ||
120 | load_dir = opendir(load_path); | ||
121 | if (!load_dir) { | ||
122 | core_err(fw, "%s: Unable to open dir (%s)\n", | ||
123 | load_path, strerror(errno)); | ||
124 | return NULL; | ||
125 | } | ||
126 | |||
127 | while (readdir(load_dir) != NULL) | ||
128 | nr_modules += 1; | ||
129 | |||
130 | /* '.' and '..' should be skipped. */ | ||
131 | nr_modules -= 2; | ||
132 | |||
133 | /* | ||
134 | * Now allocate necessary space for storing pointers to the modules and | ||
135 | * load the modules. +1 for the last NULL entry. | ||
136 | */ | ||
137 | modules = malloc(sizeof(*modules) * (nr_modules + 1)); | ||
138 | if (!modules) { | ||
139 | core_err(fw, "Out of mem! (huh?)\n"); | ||
140 | goto err; | ||
141 | } | ||
142 | |||
143 | rewinddir(load_dir); | ||
144 | i = 0; | ||
145 | while ((ent = readdir(load_dir)) != NULL) { | ||
146 | if (strcmp(".", ent->d_name) == 0 || | ||
147 | strcmp("..", ent->d_name) == 0) | ||
148 | continue; | ||
149 | |||
150 | mod = load_one_module(fw, ent); | ||
151 | if (mod == NULL) | ||
152 | continue; | ||
153 | |||
154 | if (check_module(fw, mod) != 0) | ||
155 | continue; | ||
156 | |||
157 | modules[i] = mod; | ||
158 | i++; | ||
159 | } | ||
160 | |||
161 | modules[i] = NULL; | ||
162 | return modules; | ||
163 | |||
164 | err: | ||
165 | closedir(load_dir); | ||
166 | return NULL; | ||
167 | } | ||
diff --git a/userspace/src/nvgpu.c b/userspace/src/nvgpu.c new file mode 100644 index 00000000..a9b7ced3 --- /dev/null +++ b/userspace/src/nvgpu.c | |||
@@ -0,0 +1,78 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved. | ||
3 | * | ||
4 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
5 | * copy of this software and associated documentation files (the "Software"), | ||
6 | * to deal in the Software without restriction, including without limitation | ||
7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
8 | * and/or sell copies of the Software, and to permit persons to whom the | ||
9 | * Software is furnished to do so, subject to the following conditions: | ||
10 | * | ||
11 | * The above copyright notice and this permission notice shall be included in | ||
12 | * all copies or substantial portions of the Software. | ||
13 | * | ||
14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
17 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | ||
19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | ||
20 | * DEALINGS IN THE SOFTWARE. | ||
21 | */ | ||
22 | |||
23 | #include <dlfcn.h> | ||
24 | #include <stdlib.h> | ||
25 | |||
26 | #include <unit/io.h> | ||
27 | #include <unit/core.h> | ||
28 | |||
29 | /* | ||
30 | * Load libnvgpu-drv.so. This is done with dlopen() since this will make | ||
31 | * resolving addresses into symbols easier in the future. | ||
32 | * | ||
33 | * Also, this makes people think carefully about what functions to call in | ||
34 | * nvgpu-drv from the unit test FW. The interaction should really be limited | ||
35 | * and doing explicit name lookups is a good way to prevent too much coupling. | ||
36 | */ | ||
37 | int core_load_nvgpu(struct unit_fw *fw) | ||
38 | { | ||
39 | const char *msg; | ||
40 | |||
41 | /* | ||
42 | * Specify a GLOBAL binding so that subsequently loaded unit tests see | ||
43 | * the nvgpu-drv library. They will of course need it (and will access | ||
44 | * it directly). I.e they will link against nvgpu-drv and this should | ||
45 | * satisfy that linkage. | ||
46 | */ | ||
47 | fw->nvgpu_so = dlopen("libnvgpu-drv.so", RTLD_NOW | RTLD_GLOBAL); | ||
48 | |||
49 | if (fw->nvgpu_so == NULL) { | ||
50 | msg = dlerror(); | ||
51 | core_err(fw, "Failed to load nvgpu-drv: %s\n", msg); | ||
52 | return -1; | ||
53 | } | ||
54 | |||
55 | /* | ||
56 | * We directly check the value of the returned symbol for these | ||
57 | * functions against NULL because if it is NULL then something is | ||
58 | * terribly wrong. | ||
59 | */ | ||
60 | |||
61 | fw->nvgpu.nvgpu_posix_probe = dlsym(fw->nvgpu_so, | ||
62 | "nvgpu_posix_probe"); | ||
63 | if (fw->nvgpu.nvgpu_posix_probe == NULL) { | ||
64 | msg = dlerror(); | ||
65 | core_err(fw, "Failed to resolve nvgpu_posix_probe: %s\n", msg); | ||
66 | return -1; | ||
67 | } | ||
68 | |||
69 | fw->nvgpu.nvgpu_posix_cleanup = dlsym(fw->nvgpu_so, | ||
70 | "nvgpu_posix_cleanup"); | ||
71 | if (fw->nvgpu.nvgpu_posix_cleanup == NULL) { | ||
72 | msg = dlerror(); | ||
73 | core_err(fw, "Failed to resolve nvgpu_posix_cleanup: %s\n", msg); | ||
74 | return -1; | ||
75 | } | ||
76 | |||
77 | return 0; | ||
78 | } | ||
diff --git a/userspace/src/results.c b/userspace/src/results.c new file mode 100644 index 00000000..ae077b82 --- /dev/null +++ b/userspace/src/results.c | |||
@@ -0,0 +1,128 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved. | ||
3 | * | ||
4 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
5 | * copy of this software and associated documentation files (the "Software"), | ||
6 | * to deal in the Software without restriction, including without limitation | ||
7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
8 | * and/or sell copies of the Software, and to permit persons to whom the | ||
9 | * Software is furnished to do so, subject to the following conditions: | ||
10 | * | ||
11 | * The above copyright notice and this permission notice shall be included in | ||
12 | * all copies or substantial portions of the Software. | ||
13 | * | ||
14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
17 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | ||
19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | ||
20 | * DEALINGS IN THE SOFTWARE. | ||
21 | */ | ||
22 | |||
23 | #include <stdlib.h> | ||
24 | #include <string.h> | ||
25 | |||
26 | #include <unit/io.h> | ||
27 | #include <unit/core.h> | ||
28 | #include <unit/unit.h> | ||
29 | #include <unit/results.h> | ||
30 | |||
31 | static int __init_results(struct unit_fw *fw) | ||
32 | { | ||
33 | struct unit_results *results; | ||
34 | |||
35 | if (fw->results != NULL) | ||
36 | return 0; | ||
37 | |||
38 | results = malloc(sizeof(*results)); | ||
39 | if (results == NULL) | ||
40 | return -1; | ||
41 | |||
42 | memset(results, 0, sizeof(*results)); | ||
43 | |||
44 | fw->results = results; | ||
45 | |||
46 | return 0; | ||
47 | } | ||
48 | |||
49 | static void add_record(struct unit_test_list *list, | ||
50 | struct unit_test_record *tr) | ||
51 | { | ||
52 | /* | ||
53 | * First entry. | ||
54 | */ | ||
55 | if (list->head == NULL) { | ||
56 | list->head = tr; | ||
57 | list->last = tr; | ||
58 | return; | ||
59 | } | ||
60 | |||
61 | /* | ||
62 | * Add to the end of the list and update the pointer to the last entry | ||
63 | * in the list. This gives us O(1) add time. | ||
64 | */ | ||
65 | list->last->next = tr; | ||
66 | list->last = tr; | ||
67 | } | ||
68 | |||
69 | int core_add_test_record(struct unit_fw *fw, | ||
70 | struct unit_module *mod, | ||
71 | struct unit_module_test *test, | ||
72 | bool success) | ||
73 | { | ||
74 | struct unit_test_record *tr; | ||
75 | |||
76 | /* | ||
77 | * Dones nothing if results are already inited. | ||
78 | */ | ||
79 | if (__init_results(fw) != 0) | ||
80 | return -1; | ||
81 | |||
82 | tr = malloc(sizeof(*tr)); | ||
83 | if (tr == NULL) | ||
84 | return -1; | ||
85 | |||
86 | tr->mod = mod; | ||
87 | tr->test = test; | ||
88 | tr->status = success; | ||
89 | tr->next = NULL; | ||
90 | |||
91 | if (success) | ||
92 | add_record(&fw->results->passing, tr); | ||
93 | else | ||
94 | add_record(&fw->results->failing, tr); | ||
95 | |||
96 | fw->results->nr_tests += 1; | ||
97 | if (success) | ||
98 | fw->results->nr_passing += 1; | ||
99 | |||
100 | return 0; | ||
101 | } | ||
102 | |||
103 | void core_print_test_status(struct unit_fw *fw) | ||
104 | { | ||
105 | struct unit_test_list *failing_tests = &fw->results->failing; | ||
106 | struct unit_test_record *rec; | ||
107 | |||
108 | /* | ||
109 | * Print stats for the tests. | ||
110 | */ | ||
111 | core_msg(fw, "\n"); | ||
112 | core_msg(fw, "Test results:\n"); | ||
113 | core_msg(fw, "-------------\n"); | ||
114 | core_msg(fw, "\n"); | ||
115 | core_msg(fw, " Passing: %d\n", fw->results->nr_passing); | ||
116 | core_msg(fw, " Failing: %d\n", | ||
117 | fw->results->nr_tests - fw->results->nr_passing); | ||
118 | core_msg(fw, " Total: %d\n", fw->results->nr_tests); | ||
119 | core_msg(fw, "\n"); | ||
120 | core_msg(fw, "Failing tests:\n"); | ||
121 | core_msg(fw, "\n"); | ||
122 | |||
123 | for_record_in_test_list(failing_tests, rec) { | ||
124 | core_msg(fw, " %s.%s\n", | ||
125 | rec->mod->name, | ||
126 | rec->test->name); | ||
127 | } | ||
128 | } | ||
diff --git a/userspace/src/unit_main.c b/userspace/src/unit_main.c new file mode 100644 index 00000000..31c31d50 --- /dev/null +++ b/userspace/src/unit_main.c | |||
@@ -0,0 +1,76 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved. | ||
3 | * | ||
4 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
5 | * copy of this software and associated documentation files (the "Software"), | ||
6 | * to deal in the Software without restriction, including without limitation | ||
7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
8 | * and/or sell copies of the Software, and to permit persons to whom the | ||
9 | * Software is furnished to do so, subject to the following conditions: | ||
10 | * | ||
11 | * The above copyright notice and this permission notice shall be included in | ||
12 | * all copies or substantial portions of the Software. | ||
13 | * | ||
14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
17 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | ||
19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | ||
20 | * DEALINGS IN THE SOFTWARE. | ||
21 | */ | ||
22 | |||
23 | /** | ||
24 | * NvGpu unit testing framework! | ||
25 | */ | ||
26 | |||
27 | #include <stdlib.h> | ||
28 | #include <string.h> | ||
29 | |||
30 | #include <unit/io.h> | ||
31 | #include <unit/core.h> | ||
32 | #include <unit/args.h> | ||
33 | #include <unit/module.h> | ||
34 | #include <unit/results.h> | ||
35 | |||
36 | int main(int argc, char **argv) | ||
37 | { | ||
38 | struct unit_fw *fw; | ||
39 | int ret; | ||
40 | |||
41 | fw = malloc(sizeof(*fw)); | ||
42 | if (!fw) | ||
43 | return 1; | ||
44 | |||
45 | memset(fw, 0, sizeof(*fw)); | ||
46 | |||
47 | ret = core_parse_args(fw, argc, argv); | ||
48 | if (ret) { | ||
49 | core_err(fw, "Enable to parse args.\n"); | ||
50 | core_err(fw, "Exiting!\n"); | ||
51 | return 1; | ||
52 | } | ||
53 | |||
54 | core_vbs(fw, 1, "Welcome to the nvgpu unit testing framework!\n"); | ||
55 | |||
56 | if (args(fw)->help) { | ||
57 | core_print_help(fw); | ||
58 | return 1; | ||
59 | } | ||
60 | |||
61 | ret = core_load_nvgpu(fw); | ||
62 | if (ret != 0) | ||
63 | return ret; | ||
64 | |||
65 | fw->modules = core_load_modules(fw); | ||
66 | if (fw->modules == NULL) | ||
67 | return -1; | ||
68 | |||
69 | ret = core_exec(fw); | ||
70 | if (ret != 0) | ||
71 | return ret; | ||
72 | |||
73 | core_print_test_status(fw); | ||
74 | |||
75 | return 0; | ||
76 | } | ||
diff --git a/userspace/unit.sh b/userspace/unit.sh new file mode 100755 index 00000000..078512f8 --- /dev/null +++ b/userspace/unit.sh | |||
@@ -0,0 +1,16 @@ | |||
1 | #!/bin/bash | ||
2 | |||
3 | # | ||
4 | # Execute the unit test. Args to this script are passed on to the unit test | ||
5 | # core. This just serves to set the LD_LIBRARY_PATH environment variable such | ||
6 | # that unit tests are found and nvgpu-drv is found. | ||
7 | # | ||
8 | |||
9 | LD_LIBRARY_PATH="build:build/units" | ||
10 | NVGPU_UNIT=build/nvgpu_unit | ||
11 | |||
12 | export LD_LIBRARY_PATH | ||
13 | |||
14 | echo "$ $NVGPU_UNIT $*" | ||
15 | |||
16 | $NVGPU_UNIT $* | ||
diff --git a/userspace/units/Makefile.units b/userspace/units/Makefile.units new file mode 100644 index 00000000..64b9e07d --- /dev/null +++ b/userspace/units/Makefile.units | |||
@@ -0,0 +1,45 @@ | |||
1 | # -*- mode: makefile -*- | ||
2 | # | ||
3 | # Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved. | ||
4 | # | ||
5 | # Permission is hereby granted, free of charge, to any person obtaining a | ||
6 | # copy of this software and associated documentation files (the "Software"), | ||
7 | # to deal in the Software without restriction, including without limitation | ||
8 | # the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
9 | # and/or sell copies of the Software, and to permit persons to whom the | ||
10 | # Software is furnished to do so, subject to the following conditions: | ||
11 | # | ||
12 | # The above copyright notice and this permission notice shall be included in | ||
13 | # all copies or substantial portions of the Software. | ||
14 | # | ||
15 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
16 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
17 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
18 | # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
19 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | ||
20 | # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | ||
21 | # DEALINGS IN THE SOFTWARE. | ||
22 | |||
23 | # | ||
24 | # Inlcude this in unit test makefiles to get useful rules. | ||
25 | # | ||
26 | |||
27 | LOCAL_HEADERS = (shell ls *.h) | ||
28 | |||
29 | .PHONY: all clean | ||
30 | all: lib$(MODULE).so | ||
31 | @true | ||
32 | |||
33 | # | ||
34 | # Inherits from the top level makefile. As such the unit test make files cannot | ||
35 | # be invoked by themselves. | ||
36 | %.o : %.c # $(LOCAL_HEADERS) | ||
37 | $(CC) $(CFLAGS) -c -o $@ $< | ||
38 | |||
39 | lib$(MODULE).so: $(OBJS) | ||
40 | $(CC) -shared -o $@ $(OBJS) | ||
41 | @mkdir -p $(UNIT_OUT)/ | ||
42 | @cp $@ $(UNIT_OUT)/ | ||
43 | |||
44 | clean: | ||
45 | rm -rf *.o *.so | ||