[ostree/wip/pull] Some bits to run apache



commit 9b97735cfc21ffdcc1b7632f619441b4d4c8d2fc
Author: Colin Walters <walters verbum org>
Date:   Sun Oct 30 17:27:32 2011 -0400

    Some bits to run apache

 tests/Makefile                                     |    9 +-
 tests/libtest.sh                                   |   38 ++++-
 tests/run-apache.c                                 |  167 ++++++++++++++++++++
 tests/t0012-pull.sh                                |    2 +-
 tests/{ostree-http-server.c => tmpdir-lifecycle.c} |   92 +++++------
 5 files changed, 247 insertions(+), 61 deletions(-)
---
diff --git a/tests/Makefile b/tests/Makefile
index e35744b..6beba04 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -20,10 +20,13 @@
 
 TESTS = $(wildcard t[0-9][0-9][0-9][0-9]-*.sh)
 
-all: ostree-http-server
+all: tmpdir-lifecycle run-apache
 
-ostree-http-server: ostree-http-server.c Makefile
-	gcc $(CFLAGS) `pkg-config --cflags --libs libsoup-gnome-2.4` -o ostree-http-server $<
+tmpdir-lifecycle: tmpdir-lifecycle.c Makefile
+	gcc $(CFLAGS) `pkg-config --cflags --libs gio-unix-2.0` -o $@ $<
+
+run-apache: run-apache.c Makefile
+	gcc $(CFLAGS) `pkg-config --cflags --libs gio-unix-2.0` -o $@ $<
 
 check:
 	@for test in $(TESTS); do \
diff --git a/tests/libtest.sh b/tests/libtest.sh
index 9e50e4d..3bf3857 100644
--- a/tests/libtest.sh
+++ b/tests/libtest.sh
@@ -96,25 +96,45 @@ setup_test_repository2 () {
 
 setup_fake_remote_repo1() {
     oldpwd=`pwd`
-    mkdir remote
-    ostree init --repo=remote
-    mkdir remote-files
-    cd remote-files 
+    mkdir ostree-srv
+    cd ostree-srv
+    mkdir gnomerepo
+    ostree init --repo=gnomerepo
+    mkdir gnomerepo-files
+    cd gnomerepo-files 
     echo first > firstfile
     mkdir baz
     echo moo > baz/cow
     echo alien > baz/saucer
-    find | grep -v '^\.$' | ostree commit --repo=${test_tmpdir}/remote -b main -s "A remote commit" -m "Some Commit body" --from-stdin
+    find | grep -v '^\.$' | ostree commit --repo=${test_tmpdir}/ostree-srv/gnomerepo -b main -s "A remote commit" -m "Some Commit body" --from-stdin
     mkdir baz/deeper
-    ostree commit --repo=${test_tmpdir}/remote -b main -s "Add deeper" --add=baz/deeper
+    ostree commit --repo=${test_tmpdir}/ostree-srv/gnomerepo -b main -s "Add deeper" --add=baz/deeper
     echo hi > baz/deeper/ohyeah
     mkdir baz/another/
     echo x > baz/another/y
-    find | grep -v '^\.$' | ostree commit --repo=${test_tmpdir}/remote -b main -s "The rest" --from-stdin
+    find | grep -v '^\.$' | ostree commit --repo=${test_tmpdir}/ostree-srv/gnomerepo -b main -s "The rest" --from-stdin
     cd ..
-    rm -rf remote-files
+    rm -rf gnomerepo-files
     
-    ${SRCDIR}/ostree-http-server > ${test_tmpdir}/remote-address &
+    cd ${test_tmpdir}
+    mkdir ${test_tmpdir}/httpd
+    cd httpd
+    cat >httpd.conf <<EOF
+ServerRoot ${test_tmpdir}/httpd
+PidFile pid
+LogLevel crit
+ErrorLog log
+LockFile lock
+ServerName localhost
+
+LoadModule alias_module modules/mod_alias.so
+LoadModule cgi_module modules/mod_cgi.so
+LoadModule env_module modules/mod_env.so
+
+SetEnv OSTREE_PROJECT_ROOT ${test_tmpdir}/ostree-srv
+ScriptAlias /ostree/  ${test_tmpdir}/ostree-http-backend/
+EOF
+    ${SRCDIR}/tmpdir-lifecycle ${SRCDIR}/run-apache `pwd`/httpd.conf ${test_tmpdir}/httpd-address
     cd ${oldpwd} 
 }
 
diff --git a/tests/run-apache.c b/tests/run-apache.c
new file mode 100644
index 0000000..b5f7e5c
--- /dev/null
+++ b/tests/run-apache.c
@@ -0,0 +1,167 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
+ *
+ * Copyright (C) 2011 Colin Walters <walters verbum org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Author: Colin Walters <walters verbum org>
+ */
+
+#include <gio/gio.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+#include <errno.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <sys/stat.h>
+
+/* Taken from gnome-user-share src/httpd.c under the GPLv2 */
+static int
+get_port (void)
+{
+  int sock;
+  int saved_errno;
+  struct sockaddr_in addr;
+  int reuse;
+  socklen_t len;
+
+  sock = socket (PF_INET, SOCK_STREAM, 0);
+  if (sock < 0)
+    {
+      return -1;
+    }
+  
+  memset (&addr, 0, sizeof (addr));
+  addr.sin_family = AF_INET;
+  addr.sin_port = 0;
+  addr.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
+
+  reuse = 1;
+  setsockopt (sock, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof (reuse));
+  if (bind (sock, (struct sockaddr *)&addr, sizeof (addr)) == -1)
+    {
+      saved_errno = errno;
+      close (sock);
+      errno = saved_errno;
+      return -1;
+    }
+
+  len = sizeof (addr);
+  if (getsockname (sock, (struct sockaddr *)&addr, &len) == -1)
+    {
+      saved_errno = errno;
+      close (sock);
+      errno = saved_errno;
+      return -1;
+    }
+
+#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__APPLE__)
+  /* XXX This exposes a potential race condition, but without this,
+   * httpd will not start on the above listed platforms due to the fact
+   * that SO_REUSEADDR is also needed when Apache binds to the listening
+   * socket.  At this time, Apache does not support that socket option.
+   */
+  close (sock);
+#endif
+  return ntohs (addr.sin_port);
+}
+
+static const char *known_httpd_modules_locations [] = {
+  "/usr/libexec/apache2",
+  "/usr/lib/apache2/modules",
+  "/usr/lib64/httpd/modules",
+  "/usr/lib/httpd/modules",
+  NULL
+};
+
+static gchar*
+get_httpd_modules_path ()
+{
+  int i;
+
+  for (i = 0; known_httpd_modules_locations[i]; i++)
+    {
+      if (g_file_test (known_httpd_modules_locations[i], G_FILE_TEST_IS_EXECUTABLE)
+	  && g_file_test (known_httpd_modules_locations[i], G_FILE_TEST_IS_DIR))
+	{
+	  return g_strdup (known_httpd_modules_locations[i]);
+	}
+    }
+  return NULL;
+}
+
+int
+main (int     argc,
+      char  **argv)
+{
+  int port;
+  char *listen;
+  char *address_string;
+  GError *error = NULL;
+  GPtrArray *httpd_argv;
+  char *modules;
+
+  if (argc != 3)
+    {
+      fprintf (stderr, "usage: run-apache CONF PORTFILE");
+      return 1;
+    }
+
+  g_type_init ();
+
+  port = get_port ();
+  if (port == -1)
+    {
+      perror ("Failed to bind port");
+      return 1;
+    }
+
+  httpd_argv = g_ptr_array_new ();
+  g_ptr_array_add (httpd_argv, "httpd");
+  g_ptr_array_add (httpd_argv, "-f");
+  g_ptr_array_add (httpd_argv, argv[1]);
+  g_ptr_array_add (httpd_argv, "-C");
+  listen = g_strdup_printf ("Listen 127.0.0.1:%d", port);
+  g_ptr_array_add (httpd_argv, listen);
+  g_ptr_array_add (httpd_argv, NULL);
+
+  address_string = g_strdup_printf ("http://127.0.0.1:%d\n";, port);
+  
+  if (!g_file_set_contents (argv[2], address_string, -1, &error))
+    {
+      g_printerr ("%s\n", error->message);
+      return 1;
+    }
+
+  setenv ("LANG", "C", 1);
+  modules = get_httpd_modules_path ();
+  if (modules == NULL)
+    {
+      g_printerr ("Failed to find httpd modules\n");
+      return 1;
+    }
+  if (symlink (modules, "modules") < 0)
+    {
+      perror ("failed to make modules symlink");
+      return 1;
+    }
+  execvp ("httpd", (char**)httpd_argv->pdata);
+  perror ("Failed to run httpd");
+  return 1;
+}
diff --git a/tests/t0012-pull.sh b/tests/t0012-pull.sh
index ab3ac91..e17d9cf 100755
--- a/tests/t0012-pull.sh
+++ b/tests/t0012-pull.sh
@@ -29,6 +29,6 @@ setup_fake_remote_repo1
 cd ${test_tmpdir}
 mkdir repo
 ostree init --repo=repo
-ostree remote --repo=repo add origin $(cat remote-address)/remote
+ostree remote --repo=repo add origin $(cat httpd-address)/gnomerepo
 ostree pull --repo=repo origin main
 echo "ok pull"
diff --git a/tests/ostree-http-server.c b/tests/tmpdir-lifecycle.c
similarity index 51%
rename from tests/ostree-http-server.c
rename to tests/tmpdir-lifecycle.c
index a6c0279..95aae63 100644
--- a/tests/ostree-http-server.c
+++ b/tests/tmpdir-lifecycle.c
@@ -1,5 +1,7 @@
 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
  *
+ * Kill a child process when the current directory is deleted
+ *
  * Copyright (C) 2011 Colin Walters <walters verbum org>
  *
  * This program is free software; you can redistribute it and/or modify
@@ -19,38 +21,16 @@
  * Author: Colin Walters <walters verbum org>
  */
 
-#include <libsoup/soup-gnome.h>
-#include <sys/types.h>
+#include <gio/gio.h>
 #include <unistd.h>
 #include <stdlib.h>
+#include <string.h>
 
-static void
-request_callback (SoupServer *server, SoupMessage *msg,
-		  const char *path, GHashTable *query,
-		  SoupClientContext *context, gpointer data)
-{
-  if (msg->method == SOUP_METHOD_GET) 
-    {
-      GFile *file;
-      char *content;
-      gsize len;
-      
-      /* Strip leading / */
-      file = g_file_new_for_path (path + 1);
-      
-      if (g_file_load_contents (file, NULL, &content, &len, NULL, NULL))
-	{
-	  soup_message_set_response (msg, "application/octet-stream", SOUP_MEMORY_TAKE, content, len);
-	  soup_message_set_status (msg, SOUP_STATUS_OK);
-	}
-      else
-	soup_message_set_status (msg, SOUP_STATUS_NOT_FOUND);
-    }
-  else
-    {
-      soup_message_set_status (msg, SOUP_STATUS_METHOD_NOT_ALLOWED);
-    }
-}
+struct TmpdirLifecyleData {
+  GMainLoop *loop;
+  GPid pid;
+  gboolean exited;
+};
 
 static void
 on_dir_changed (GFileMonitor  *mon,
@@ -59,49 +39,65 @@ on_dir_changed (GFileMonitor  *mon,
 		GFileMonitorEvent  event,
 		gpointer user_data)
 {
-  GMainLoop *loop = user_data;
+  struct TmpdirLifecyleData *data = user_data;
 
   if (event == G_FILE_MONITOR_EVENT_DELETED)
-    g_main_loop_quit (loop);
+    g_main_loop_quit (data->loop);
+}
+
+static void
+on_child_exited (GPid  pid,
+                 int status,
+                 gpointer user_data)
+{
+  struct TmpdirLifecyleData *data = user_data;
+
+  data->exited = TRUE;
+  g_main_loop_quit (data->loop);
 }
 
 int
 main (int     argc,
       char  **argv)
 {
-  SoupAddress *addr;
-  SoupServer *server;
-  GMainLoop *loop;
   GFileMonitor *monitor;
   GFile *curdir;
   GError *error = NULL;
+  GPtrArray *new_argv;
+  int i;
+  GPid pid;
+  struct TmpdirLifecyleData data;
 
   g_type_init ();
 
-  loop = g_main_loop_new (NULL, TRUE);
+  memset (&data, 0, sizeof (data));
+
+  data.loop = g_main_loop_new (NULL, TRUE);
 
   curdir = g_file_new_for_path (".");
   monitor = g_file_monitor_directory (curdir, 0, NULL, &error);
   if (!monitor)
     exit (1);
   g_signal_connect (monitor, "changed",
-		    G_CALLBACK (on_dir_changed), loop);
-
-  addr = soup_address_new ("127.0.0.1", SOUP_ADDRESS_ANY_PORT);
-  soup_address_resolve_sync (addr, NULL);
+		    G_CALLBACK (on_dir_changed), &data);
 
-  server = soup_server_new (SOUP_SERVER_INTERFACE, addr,
-			    SOUP_SERVER_ASYNC_CONTEXT, g_main_loop_get_context (loop),
-			    NULL);
-  soup_server_add_handler (server, NULL,
-			   request_callback,
-			   NULL, NULL);
+  new_argv = g_ptr_array_new ();
+  for (i = 1; i < argc; i++)
+    g_ptr_array_add (new_argv, argv[i]);
+  g_ptr_array_add (new_argv, NULL);
 
-  soup_server_run_async (server);
+  if (!g_spawn_async (NULL, (char**)new_argv->pdata, NULL, G_SPAWN_SEARCH_PATH | G_SPAWN_DO_NOT_REAP_CHILD,
+                      NULL, NULL, &pid, &error))
+    {
+      g_printerr ("%s\n", error->message);
+      return 1;
+    }
+  g_child_watch_add (pid, on_child_exited, &data);
 
-  g_print ("http://127.0.0.1:%ld\n";, (long)soup_server_get_port (server));
+  g_main_loop_run (data.loop);
 
-  g_main_loop_run (loop);
+  if (!data.exited)
+    kill (data.pid, SIGTERM);
 
   return 0;
 }



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]