# -*-perl-*- $description = "Test the shared object load API."; $details = "Verify the different aspects of the shared object API."; # Don't do anything if this system doesn't support "load" exists $FEATURES{load} or return -1; my $cc = get_config('CC'); if (! $cc) { $verbose and print "Skipping load test: no CC defined\n"; return -1; } # First build a shared object # Provide both a default and non-default load symbol unlink(qw(testapi.c testapi.so)); open(my $F, '> testapi.c') or die "open: testapi.c: $!\n"; print $F <<'EOF' ; #include #include #include "gnumake.h" char *getenv (const char*); int plugin_is_GPL_compatible; int testapi_gmk_setup (); static char * test_eval (const char *buf) { gmk_eval (buf, 0); return NULL; } static char * test_expand (const char *val) { return gmk_expand (val); } static char * test_noexpand (const char *val) { char *str = gmk_alloc (strlen (val) + 1); strcpy (str, val); return str; } static char * func_test (const char *funcname, unsigned int argc, char **argv) { char *mem; if (strcmp (funcname, "test-expand") == 0) return test_expand (argv[0]); if (strcmp (funcname, "test-eval") == 0) return test_eval (argv[0]); if (strcmp (funcname, "test-noexpand") == 0) return test_noexpand (argv[0]); mem = gmk_alloc (sizeof ("unknown")); strcpy (mem, "unknown"); return mem; } int testapi_gmk_setup (const gmk_floc *floc) { const char *verbose = getenv ("TESTAPI_VERBOSE"); gmk_add_function ("test-expand", func_test, 1, 1, GMK_FUNC_DEFAULT); gmk_add_function ("test-noexpand", func_test, 1, 1, GMK_FUNC_NOEXPAND); gmk_add_function ("test-eval", func_test, 1, 1, GMK_FUNC_DEFAULT); gmk_add_function ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_.", func_test, 0, 0, 0); if (verbose) { printf ("testapi_gmk_setup\n"); if (verbose[0] == '2') printf ("%s:%lu\n", floc->filenm, floc->lineno); } if (getenv ("TESTAPI_KEEP")) return -1; return 1; } EOF close($F) or die "close: testapi.c: $!\n"; # Make sure we can compile my $cflags = get_config('CFLAGS'); my $cppflags = get_config('CPPFLAGS'); my $ldflags = get_config('LDFLAGS'); my $sobuild = "$cc ".($srcdir? "-I$srcdir/src":'')." $cppflags $cflags -shared -fPIC $ldflags -o testapi.so testapi.c"; my $clog = `$sobuild 2>&1`; if ($? != 0) { $verbose and print "Failed to build testapi.so:\n$sobuild\n$_"; return -1; } # TEST 1 # Check the gmk_expand() function run_make_test(q! EXPAND = expansion all: ; @echo $(test-expand $$(EXPAND)) load testapi.so !, '', "expansion\n"); # TEST 2 # Check the eval operation. Prove that the argument is expanded only once run_make_test(q! load testapi.so TEST = bye ASSIGN = VAR = $(TEST) $(shell echo there) $(test-eval $(value ASSIGN)) TEST = hi all:;@echo '$(VAR)' !, '', "hi there\n"); # TEST 2 # Check the no-expand capability run_make_test(q! load testapi.so TEST = hi all:;@echo '$(test-noexpand $(TEST))' !, '', "\$(TEST)\n"); # During all subsequent tests testapi.so exists. # my @loads = ('', q! load testapi.so load testapi.so -load testapi.so -load testapi.so $(eval load testapi.so) $(eval -load testapi.so) !); for my $extra_loads (@loads) { my $n = 5; if ($extra_loads) { $n = 12; } # sv 63045. # Test that having unloaded a shared object make loads it again, even if the # shared object is not updated. $ENV{TESTAPI_VERBOSE} = 1; run_make_test(" load testapi.so $extra_loads all:; \$(info \$(test-expand hello)) testapi.so: force; \$(info \$@) force:; .PHONY: force ", '', "testapi_gmk_setup\ntestapi.so\ntestapi_gmk_setup\nhello\n#MAKE#: 'all' is up to date.\n"); # sv 63045. # Same as above, but testapi_gmk_setup returned -1. $ENV{TESTAPI_KEEP} = 1; $ENV{TESTAPI_VERBOSE} = 1; run_make_test(" load testapi.so $extra_loads all:; \$(info \$(test-expand hello)) testapi.so: force; \$(info \$@) force:; .PHONY: force ", '', "testapi_gmk_setup\nhello\n#MAKE#: 'all' is up to date.\n"); # sv 63045. # Test that make exits, unless make can successfully update an unloaded shared # object. $ENV{TESTAPI_VERBOSE} = 1; run_make_test(" load testapi.so $extra_loads all:; \$(info \$(test-expand hello)) testapi.so: force; @#HELPER# fail 1 force:; .PHONY: force ", '', "testapi_gmk_setup\nfail 1\n#MAKE#: *** [#MAKEFILE#:$n: testapi.so] Error 1\n", 512); # sv 63045. # Same as above, but testapi_gmk_setup returned -1. $ENV{TESTAPI_KEEP} = 1; $ENV{TESTAPI_VERBOSE} = 1; run_make_test(" load testapi.so $extra_loads all:; \$(info \$(test-expand hello)) testapi.so: force; @#HELPER# fail 1 force:; .PHONY: force ", '', "testapi_gmk_setup\nhello\n#MAKE#: 'all' is up to date.\n"); # sv 63100. # Test that make supplies the correct floc when the shared object is loaded # again. $ENV{TESTAPI_VERBOSE} = 2; run_make_test(" load testapi.so $extra_loads all:; \$(info \$(test-expand hello)) testapi.so: force; \$(info \$@) force:; .PHONY: force ", '', "testapi_gmk_setup\n#MAKEFILE#:2\ntestapi.so\ntestapi_gmk_setup\n#MAKEFILE#:2\nhello\n#MAKE#: 'all' is up to date.\n"); } unlink(qw(testapi.c testapi.so)) unless $keep; # This tells the test driver that the perl test script executed properly. 1;