V2 test-container: ability to specify exec path

Message ID xnk172sfm6.fsf@greed.delorie.com
State Superseded
Headers

Commit Message

DJ Delorie Dec. 11, 2019, 9:43 p.m. UTC
  Florian Weimer <fweimer@redhat.com> writes:
>>> I think you should make this more explicit, because the comment above
>>> sounds like as this changes the current directory for the test.
>>
>> Do we need that too?
>
> Maybe?  I haven't seen a need for this yet.

This one adds "exec" (with optional argv[0] override) as well as "cwd"
to set the CWD of the test.
  

Comments

Florian Weimer Dec. 12, 2019, 1:18 p.m. UTC | #1
* DJ Delorie:

> +		/* Find the base name of the test.  */
> +		if (strrchr (test_basename, '/') != NULL)
> +		  test_basename = strrchr (test_basename, '/') + 1;

Can you use the basename function here?

> +		/* If the new exec path ends with a slash, that's the
> +		 * directory, and use the old test base name.  */
> +		if (new_exec_path [strlen(new_exec_path) - 1] == '/')
> +		    new_exec_path = concat (new_exec_path,
> +					    test_basename,
> +					    NULL);
> +
> +
> +		/* new_child_proc is in the build tree, so has the
> +		   same path inside the chroot as outside.  The new
> +		   exec path is, by definition, relative to the
> +		   chroot.  */
> +		copy_one_file (new_child_proc[0],  concat (new_root_path,
> +							   new_exec_path,
> +							   NULL));
> +
> +		new_child_exec =  strdup (new_exec_path);
> +		if (the_words[2])
> +		  new_child_proc[0] = strdup (the_words[2]);
> +		else
> +		  new_child_proc[0] = new_child_exec;
> +	      }
> +	    else if (nt == 2 && strcmp (the_words[0], "cwd") == 0)
> +	      {
> +		change_cwd = strdup (the_words[1]);

Use xstrdup (twice)?

Rest looks okay to me, based on cursory glance.

Thanks,
Florian
  

Patch

diff --git a/nss/tst-nss-test3.root/tst-nss-test3.script b/nss/tst-nss-test3.root/tst-nss-test3.script
index a10beb1e6c..d5b437ceb0 100644
--- a/nss/tst-nss-test3.root/tst-nss-test3.script
+++ b/nss/tst-nss-test3.root/tst-nss-test3.script
@@ -1,2 +1,4 @@ 
 cp $B/nss/libnss_test1.so $L/libnss_test1.so.2
 cp $B/nss/libnss_test2.so $L/libnss_test2.so.2
+cwd /usr/bin
+exec /usr/bin/foo bar
diff --git a/support/test-container.c b/support/test-container.c
index 5d08979df3..efdad46cc8 100644
--- a/support/test-container.c
+++ b/support/test-container.c
@@ -95,6 +95,8 @@  int verbose = 0;
          mv FILE FILE
 	 cp FILE FILE
 	 rm FILE
+	 cwd PATH
+	 exec FILE
 	 FILE must start with $B/, $S/, $I/, $L/, or /
 	  (expands to build dir, source dir, install dir, library dir
 	   (in container), or container's root)
@@ -104,6 +106,8 @@  int verbose = 0;
          - 'mv': A minimal move files command.
          - 'cp': A minimal copy files command.
          - 'rm': A minimal remove files command.
+	 - 'cwd': set test working directory
+	 - 'exec': change test binary location (may end in /)
    * mytest.root/postclean.req causes fresh rsync (with delete) after
      test if present
 
@@ -670,11 +674,13 @@  main (int argc, char **argv)
   char *new_objdir_path;
   char *new_srcdir_path;
   char **new_child_proc;
+  char *new_child_exec;
   char *command_root;
   char *command_base;
   char *command_basename;
   char *so_base;
   int do_postclean = 0;
+  char *change_cwd = NULL;
 
   int pipes[2];
   char pid_buf[20];
@@ -752,6 +758,7 @@  main (int argc, char **argv)
 				  "/testroot.root", NULL));
   new_cwd_path = get_current_dir_name ();
   new_child_proc = argv + 1;
+  new_child_exec = argv[0];
 
   lock_fd = open (concat (pristine_root_path, "/lock.fd", NULL),
 		 O_CREAT | O_TRUNC | O_RDWR, 0666);
@@ -868,7 +875,10 @@  main (int argc, char **argv)
 		  the_words[i] = concat (new_root_path,
 					 support_libdir_prefix,
 					 the_words[i] + 2, NULL);
-		else if (the_words[i][0] == '/')
+		/* "exec" and "cwd" use inside-root paths.  */
+		else if (strcmp (the_words[0], "exec") != 0
+			 && strcmp (the_words[0], "cwd") != 0
+			 && the_words[i][0] == '/')
 		  the_words[i] = concat (new_root_path,
 					 the_words[i], NULL);
 	      }
@@ -912,13 +922,54 @@  main (int argc, char **argv)
 	      {
 		maybe_xunlink (the_words[1]);
 	      }
+	    else if (nt >= 2 && strcmp (the_words[0], "exec") == 0)
+	      {
+		/* The first argument is the desired location and name
+		   of the test binary as we wish to exec it; we will
+		   copy the binary there.  The second (optional)
+		   argument is the value to pass as argv[0], it
+		   defaults to the same as the first argument.  */
+		char *new_exec_path = the_words[1];
+		char *test_basename = new_child_proc[0];
+
+		/* Find the base name of the test.  */
+		if (strrchr (test_basename, '/') != NULL)
+		  test_basename = strrchr (test_basename, '/') + 1;
+
+		/* If the new exec path ends with a slash, that's the
+		 * directory, and use the old test base name.  */
+		if (new_exec_path [strlen(new_exec_path) - 1] == '/')
+		    new_exec_path = concat (new_exec_path,
+					    test_basename,
+					    NULL);
+
+
+		/* new_child_proc is in the build tree, so has the
+		   same path inside the chroot as outside.  The new
+		   exec path is, by definition, relative to the
+		   chroot.  */
+		copy_one_file (new_child_proc[0],  concat (new_root_path,
+							   new_exec_path,
+							   NULL));
+
+		new_child_exec =  strdup (new_exec_path);
+		if (the_words[2])
+		  new_child_proc[0] = strdup (the_words[2]);
+		else
+		  new_child_proc[0] = new_child_exec;
+	      }
+	    else if (nt == 2 && strcmp (the_words[0], "cwd") == 0)
+	      {
+		change_cwd = strdup (the_words[1]);
+	      }
 	    else if (nt == 1 && strcmp (the_words[0], "su") == 0)
 	      {
 		be_su = 1;
 	      }
 	    else if (nt > 0 && the_words[0][0] != '#')
 	      {
-		printf ("\033[31minvalid [%s]\033[0m\n", the_words[0]);
+		fprintf (stderr, "\033[31minvalid [%s]\033[0m\n", the_words[0]);
+		exit (1);
 	      }
 	  }
 	fclose (f);
@@ -1089,8 +1140,14 @@  main (int argc, char **argv)
   write (GMAP, tmp, strlen (tmp));
   xclose (GMAP);
 
+  if (change_cwd)
+    {
+      if (chdir (change_cwd) < 0)
+	FAIL_EXIT1 ("Can't cd to %s inside container - ", change_cwd);
+    }
+
   /* Now run the child.  */
-  execvp (new_child_proc[0], new_child_proc);
+  execvp (new_child_exec, new_child_proc);
 
   /* Or don't run the child?  */
   FAIL_EXIT1 ("Unable to exec %s\n", new_child_proc[0]);