[Cbe-oss-dev] [PATCH 2/3] libspe2: Add test framework

Kazunori Asayama asayama at sm.sony.co.jp
Wed Mar 26 19:28:42 EST 2008


This patch adds test framework as following:

  - modify Makefile to make it easy to add and run tests
  - add common test utilities
  - modify existing tests to use the framework

Signed-off-by: Kazunori Asayama <asayama at sm.sony.co.jp>

---
 Makefile                    |    8 +
 make.defines                |    1 
 tests/Makefile              |  256 ++++++++++++++++++++++++++++++++++++--------
 tests/README                |  193 +++++++++++++++++++++++++++++++++
 tests/common_libspe2_test.h |   61 ++++++++++
 tests/ppu_file.c            |  119 ++++++++++++++++++++
 tests/ppu_libspe2_test.h    |  168 ++++++++++++++++++++++++++++
 tests/ppu_main.c            |  105 ++++++++++++++++++
 tests/ppu_misc.c            |   60 ++++++++++
 tests/ppu_result.c          |  213 ++++++++++++++++++++++++++++++++++++
 tests/ppu_thread.c          |  141 ++++++++++++++++++++++++
 tests/spu_libspe2_test.h    |   81 +++++++++++++
 tests/testevent1.c          |    2 
 tests/testevent2.c          |    2 
 tests/testinfo.c            |    2 
 tests/testlibspe2.c         |    2 
 tests/testmap1.c            |    2 
 tests/testmbox.c            |    2 
 tests/testpthread.c         |    2 
 tests/testpthreadmini.c     |    4 
 tests/testsingle.c          |    2 
 tests/testsinglemini.c      |    4 
 22 files changed, 1374 insertions(+), 56 deletions(-)

Index: b/Makefile
===================================================================
--- a/Makefile	2008-03-26 15:32:18.000000000 +0900
+++ b/Makefile	2008-03-26 15:32:32.000000000 +0900
@@ -92,7 +92,7 @@ elfspe-install:
 libspe12-install:
 	$(MAKE) -C libspe12 install
 
-tests: tests/Makefile
+tests: all
 	make -C tests
 
 ada : ada/Makefile
@@ -229,7 +229,11 @@ tests-clean:
 	$(MAKE) -C tests clean
 
 distclean: clean
+	$(MAKE) -C tests distclean
 	rm -rf latex
 	rm -rf html
 
-.PHONY: all clean tests tags
+check: tests
+	$(MAKE) -C tests -s check
+
+.PHONY: all clean check tests tags
Index: b/make.defines
===================================================================
--- a/make.defines	2008-03-26 15:32:18.000000000 +0900
+++ b/make.defines	2008-03-26 15:32:32.000000000 +0900
@@ -118,6 +118,7 @@ libspe2_SONAME	:= libspe2.so.${MAJOR_VER
 
 
 CC		:= ${CROSS}gcc
+EMBEDSPU	:= $(CROSS)embedspu
 CTAGS		:= ctags
 
 CFLAGS := -O2 -Wall -I. -fPIC -I$(TOP)/include -fexceptions -std=gnu99 \
Index: b/tests/Makefile
===================================================================
--- a/tests/Makefile	2008-03-26 15:32:18.000000000 +0900
+++ b/tests/Makefile	2008-03-26 15:32:32.000000000 +0900
@@ -1,56 +1,222 @@
-#*
-#* libspe2 - A wrapper library to adapt the JSRE SPU usage model to SPUFS 
-#* Copyright (C) 2005 IBM Corp. 
-#*
-#* This library is free software; you can redistribute it and/or modify it
-#* under the terms of the GNU Lesser General Public License as published by 
-#* the Free Software Foundation; either version 2.1 of the License, 
-#* or (at your option) any later version.
-#*
-#*  This library 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 Lesser General Public 
-#*  License for more details.
-#*
-#*   You should have received a copy of the GNU Lesser General Public License 
-#*   along with this library; if not, write to the Free Software Foundation, 
-#*   Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#*
+#
+#  libspe2 - A wrapper library to adapt the JSRE SPU usage model to SPUFS
+#
+#  Copyright (C) 2008 Sony Computer Entertainment Inc.
+#  Copyright 2007,2008 Sony Corp.
+#
+#  This library is free software; you can redistribute it and/or
+#  modify it under the terms of the GNU Lesser General Public
+#  License as published by the Free Software Foundation; either
+#  version 2.1 of the License, or (at your option) any later version.
+#
+#  This library 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
+#  Lesser General Public License for more details.
+#
+#  You should have received a copy of the GNU Lesser General Public
+#  License along with this library; if not, write to the Free Software
+#  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+#
 
-TOP=..
+TOP = ..
 
 include $(TOP)/make.defines
 
-CFLAGS += -I$(TOP)/spebase
-CFLAGS += -I$(TOP) -g
-CFLAGS +=  $(TEST_CFLAGS)
-
-LDFLAGS := $(CFLAGS) $(TEST_LDFLAGS)
-LDLIBS := -L$(TOP) -lspe2 -lpthread
-
-ALL := testsingle testsinglemini hello hellointr\
-		testmap1 \
-		testpthread testpthreadmini \
-		testlibspe2 testlibspe2hello \
-		testinfo testhandler \
-		testevent1 testevent2 \
-		testmbox readmbox
-
-all: $(ALL)
-
-hello: helloworld.c
-	$(SPU_CC) $(SPU_CFLAGS) -o hello helloworld.c
+# libspe2 directories
+LIBSPE2_INCLUDE = $(TOP)
+LIBSPE2_LIB = $(TOP)
 
-hellointr: hellointr.c
-	$(SPU_CC) $(SPU_CFLAGS) -o hellointr hellointr.c
+# PPU toolchain
+CFLAGS += -g -I$(LIBSPE2_INCLUDE) -I$(LIBSPE2_INCLUDE)/spebase $(TEST_CFLAGS)
+LDFLAGS = $(CFLAGS) -L$(LIBSPE2_LIB) $(TEST_LDFLAGS) -lspe2 -lpthread
 
-readmbox: readmbox.c
-	$(SPU_CC) $(SPU_CFLAGS) -o readmbox readmbox.c
+# SPU toolchain
+SPU_CFLAGS = -g -Wall -fno-builtin -Wno-format-zero-length
+SPU_LDFLAGS =
 
-testlibspe2hello: testlibspe2hello.c
-	$(SPU_CC) $(SPU_CFLAGS) -o testlibspe2hello testlibspe2hello.c
+# test paramegers
+TEST_ITERATION = 1
+TEST_VERBOSE = 0
+TEST_SPES = 4
 
+# list of test sets
+test_sets = regular basic extra
+
+
+# Main PPE programs (test cases)
+regular_main_progs = \
+	$(basic_main_progs)
+
+basic_main_progs = \
+	testsingle.elf \
+	testsinglemini.elf \
+	testpthread.elf \
+	testpthreadmini.elf \
+	testlibspe2.elf \
+	testinfo.elf \
+	testhandler.elf \
+	testevent1.elf \
+	testevent2.elf \
+	testmbox.elf
+
+extra_main_progs = \
+	testmap1.elf
+
+# Additional PPE programs
+ppu_progs =
+
+# External SPE programs
+basic_spu_progs = \
+	helloworld.spu.elf \
+	hellointr.spu.elf \
+	testlibspe2hello.spu.elf \
+	readmbox.spu.elf
+
+# Additional SPE programs
+spu_progs =
+
+
+# utility routines
+ppu_utils = ppu_main.o ppu_file.o ppu_misc.o ppu_result.o ppu_thread.o
+
+# all test cases
+all_main_progs = $(regular_main_progs) $(extra_main_progs)
+
+# add extra programs for each test case to the test set.
+$(foreach case,$(all_main_progs),$(eval ppu_progs += $($(case)_ppu_progs)))
+$(foreach case,$(all_main_progs),$(eval spu_progs += $($(case)_spu_progs)))
+
+# list of all programs
+$(foreach set,$(test_sets),$(eval ppu_progs += $($(set)_main_progs) $($(set)_ppu_progs)))
+$(foreach set,$(test_sets),$(eval spu_progs += $($(set)_spu_progs)))
+
+
+# list of ELFs
+ppu_elfs = $(filter %.elf,$(ppu_progs))
+spu_elfs = $(filter %.elf,$(spu_progs))
+
+
+# 'all' test set
+test_sets := all $(test_sets)
+
+
+# lists of test items corresponding to test sets.
+# (automatically generated from lists of programs above)
+$(foreach set,$(test_sets), \
+	$(eval $(set)_tests = $(patsubst %,check-%,$($(set)_main_progs))))
+
+all_checks = $(patsubst %,check-%,$(test_sets))
+
+
+# rules
+%.spu.elf: %.spu.o
+	$(SPU_CC) $(filter %.spu.o,$^) -o $@ $(SPU_LDFLAGS)
+
+%.spu.o: %.c
+	$(SPU_CC) $(SPU_CFLAGS) -c $< -o $@
+
+%.elf: %.o
+	$(CC) $(filter %.o,$^) -o $@ $(LDFLAGS)
+
+%.embed.o: %.spu.elf
+	$(EMBEDSPU) $(ARCH_CFLAGS) $(subst .,_,$(subst -,_,$*)) $< $@
+
+%.o: %.c
+	$(CC) $(CFLAGS) -c $< -o $@
+
+
+.PHONY: all check clean distclean help
+.PHONY: $(all_checks) $(all_tests)
+
+all: $(ppu_progs) $(spu_progs)
+
+check: check-regular
+
+$(all_checks):
+	@failed=""; \
+	for p in $($(subst -,_,$(patsubst check-%,%,$@))_tests); \
+	do \
+		$(MAKE) -s $$p || failed="$$failed $$p"; \
+	done; \
+	echo >&2; \
+	if [ -n "$$failed" ]; then \
+		echo "FAIL: $$failed" >&2; exit 1; \
+	else \
+		echo "PASS" >&2; \
+	fi
+
+$(all_tests): check-%: %
+	@[ -n "$(LIBSPE2_LIB)" ] && export LD_LIBRARY_PATH='$(LIBSPE2_LIB)'; \
+	prog=./$(patsubst check-%,%,$@); \
+	opts=" -n $(TEST_ITERATION) -s $(TEST_SPES)"; \
+	[ "$(TEST_VERBOSE)" != 0 ] && opts="$$opts -v"; \
+	echo "$$prog: RUNNING"; \
+	$$prog $$opts || failed="1"; \
+	if [ "$$failed" = 1 ]; then \
+		echo "$$prog: FAIL" >&2; exit 1; \
+	else \
+		echo "$$prog: PASS" >&2; \
+	fi
+
+# additional dependencies
+$(foreach set, $(test_sets), \
+	$(eval $($(set)_tests): $($(set)_ppu_progs) $($(set)_spu_progs)))
+$(foreach case,$(all_main_progs), \
+	$(eval $(case): $($(case)_ppu_progs) $($(case)_spu_progs)))
 
 clean:
-	rm -f $(ALL)
+	-$(RM) *.elf *.o *.tmp
+
+distclean: clean
+	-$(RM) *~
+
+help:
+	@echo; \
+	echo "Syntax:"; \
+	echo "    $$ $(MAKE) [<TEST-PARAMETERS>] [<TEST-CASE-OR-TEST-SET>]"; \
+	echo; \
+	echo "Examples:"; \
+	echo "    $$ $(MAKE) check"; \
+	echo "    $$ $(MAKE) ARCH=ppc64 check"; \
+	echo; \
+	echo "Test parameters:"; \
+	echo "    CROSS=<ppu-toolchain>     Prefix of PPU toolchain. (default: $(CROSS))"; \
+	echo "    SPU_CROSS=<spu-toolchain> Prefix of SPU toolchain. (default: $(SPU_CROSS))"; \
+	echo "    ARCH=<ppc-or-ppc64>       Whether libspe2 is 32-bit or 64-bit. (default: $(ARCH))"; \
+	echo "    LIBSPE2_INCLUDE=<dir>     Use header files in the directory <dir>. (default: $(LIBSPE2_INCLUDE))"; \
+	echo "    LIBSPE2_LIB=<dir>         Use library files in the directory <dir>. (default: $(LIBSPE2_LIB))"; \
+	echo "    TEST_STATIC=1             Use static libraries instead of shared libraries."; \
+	echo "    TEST_SPES=<n>             Number of SPEs to be used. (default: $(TEST_SPES))"; \
+	echo "                              Some tests may ignore this parameter."; \
+	echo "    TEST_ITERATION=<n>        Run each test <n> times repeatedly (default: $(TEST_ITERATION))."; \
+	echo "                              Some tests may ignore this parameter."; \
+	echo "    TEST_VERBOSE=1            Display many information while testing."; \
+	echo; \
+	echo "Test sets:"; \
+	echo "    check                     Same as 'check-regular'."; \
+	for t in $(test_sets); \
+	do \
+		echo "    check-$$t"; \
+	done; \
+	echo; \
+	echo "Individual test cases (included in the regular test set)"; \
+	for t in $(regular_tests); \
+	do \
+		echo "    $$t"; \
+	done; \
+	echo; \
+	echo "Individual test cases (not included in the regular test set)"; \
+	for t in $(extra_tests); \
+	do \
+		echo "    $$t"; \
+	done
+
+
+# dependencies between PPU code
+$(ppu_elfs:.elf=.o) $(ppu_utils): ppu_libspe2_test.h common_libspe2_test.h
+
+$(ppu_elfs): $(ppu_utils)
 
+# dependencies between SPU code
+$(spu_elfs:.spu.elf=.spu.o) $(spu_elfs): spu_libspe2_test.h common_libspe2_test.h
Index: b/tests/common_libspe2_test.h
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ b/tests/common_libspe2_test.h	2008-03-26 15:32:32.000000000 +0900
@@ -0,0 +1,61 @@
+/*
+ *  libspe2 - A wrapper library to adapt the JSRE SPU usage model to SPUFS
+ *
+ *  Copyright (C) 2008 Sony Computer Entertainment Inc.
+ *  Copyright 2007,2008 Sony Corp.
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library 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
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+/* This file provides common definitions and declarations shared
+ * between PPE and SPEs.
+ */
+
+#ifndef __COMMON_LIBSPE2_TEST_H
+#define __COMMON_LIBSPE2_TEST_H
+
+#include <assert.h>
+
+/*** configurations ***/
+
+
+/*** test parameters ***/
+#define MAX_SPES 64
+#define DEFAULT_NUM_SPES 4
+
+
+/*** limits ***/
+#define MAX_DUMMY_FDS 10000
+
+
+/*** utilities ***/
+#define ASSERT(e) assert(e)
+
+
+/*** structure to be used to record information about error in SPE
+ * test code. In the C99 handler's test cases, we can't use SPE's
+ * 'printf' function to report errors because a part of the function
+ * is implemented in the C99 handler itself. :-) So we report errors
+ * via LS by using this structure in such cases.
+ ***/
+typedef struct spe_error_info
+{
+  unsigned int code;
+  unsigned int file;
+  unsigned int line;
+  unsigned int err; /* errno */
+} spe_error_info_t;
+
+#endif /* __COMMON_LIBSPE2_TEST_H */
Index: b/tests/ppu_file.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ b/tests/ppu_file.c	2008-03-26 15:32:32.000000000 +0900
@@ -0,0 +1,119 @@
+/*
+ *  libspe2 - A wrapper library to adapt the JSRE SPU usage model to SPUFS
+ *
+ *  Copyright (C) 2008 Sony Computer Entertainment Inc.
+ *  Copyright 2008 Sony Corp.
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library 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
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+
+#include "ppu_libspe2_test.h"
+
+
+/*** SPUFS direct access ***/
+int spufs_open(const spe_context_ptr_t spe, const char *name, int mode)
+{
+  char node[256];
+
+  sprintf(node, "/spu/spethread-%lu-%lu/%s",
+	  (unsigned long)getpid(), (unsigned long)spe, name);
+  return open(node, mode);
+}
+
+/*** consuming FDs ***/
+#define DUMMY_FD_FILE "/dev/null"
+static int g_num_dummy_fd = 0;
+static int g_dummy_fd[MAX_DUMMY_FDS];
+
+int dummy_file_open(int num)
+{
+  if (num > MAX_DUMMY_FDS) {
+    eprintf("No more room for dummy FDs.\n");
+    return -1;
+  }
+
+  /* open specified number of FDs. */
+  while (g_num_dummy_fd < num) {
+    int fd;
+    fd = open(DUMMY_FD_FILE, O_RDONLY);
+    if (fd == -1) {
+      perror("open(" DUMMY_FD_FILE ")");
+      return -1;
+    }
+    g_dummy_fd[g_num_dummy_fd++] = fd;
+  }
+
+  return 0;
+}
+
+int dummy_file_open_r(int num)
+{
+  /* open files as many as possible */
+  while (1) {
+    int fd;
+    fd = open(DUMMY_FD_FILE, O_RDONLY);
+    if (fd == -1) {
+      if (errno == EMFILE) {
+	break;
+      }
+      else {
+	perror("open(" DUMMY_FD_FILE ")");
+	return -1;
+      }
+    }
+    if (g_num_dummy_fd >= MAX_DUMMY_FDS) {
+      close(fd);
+      eprintf("No more room for dummy FDs.\n");
+      return -1;
+    }
+    g_dummy_fd[g_num_dummy_fd++] = fd;
+  }
+
+  /* close specified number of FDs. */
+  while (num-- > 0) {
+    g_num_dummy_fd--;
+
+    close(g_dummy_fd[g_num_dummy_fd]);
+  }
+
+  return 0;
+}
+
+/* close all dummy files */
+void dummy_file_close(void)
+{
+  int i;
+  for (i = 0; i < g_num_dummy_fd; i++) {
+    close(g_dummy_fd[i]);
+  }
+  g_num_dummy_fd = 0;
+}
+
+int tmpfile_open(char *name, const char *base)
+{
+  static int serial = 0;
+  static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
+
+  pthread_mutex_lock(&lock);
+  sprintf(name, "%s-%lu.%u.tmp", base, (unsigned long)getpid(), serial++);
+  pthread_mutex_unlock(&lock);
+
+  return open(name, O_RDWR | O_CREAT | O_TRUNC,
+	      S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
+}
Index: b/tests/ppu_libspe2_test.h
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ b/tests/ppu_libspe2_test.h	2008-03-26 15:32:32.000000000 +0900
@@ -0,0 +1,168 @@
+/*
+ *  libspe2 - A wrapper library to adapt the JSRE SPU usage model to SPUFS
+ *
+ *  Copyright (C) 2008 Sony Computer Entertainment Inc.
+ *  Copyright 2007,2008 Sony Corp.
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library 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
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+/* This file provides definitions and declarations used by PPE. */
+
+#ifndef __PPU_LIBSPE2_TEST_H
+#define __PPU_LIBSPE2_TEST_H
+
+#include "common_libspe2_test.h"
+
+#include <libspe2.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+
+/*** main routine of the test ***/
+extern int ppu_main(int argc, char **argv, int (*test_proc)(int targc, char **targv));
+
+
+/*** parameters  ***/
+/* # of SPEs to be used (some tests ignore this value) */
+extern int NUM_SPES;
+
+
+/*** error handling and messages ***/
+/* counter to manage number of errors */
+extern int g_failed;
+/* increment the # of errors */
+#define failed() (++g_failed, eprintf("Error.\n"))
+/* report error and exit immediately */
+#define fatal() do { failed(); check_failed(); } while (0)
+/* check whether any errors have occured and exit immediately if any. */
+#define check_failed() do { if (g_failed) { exit(1); } } while (0)
+
+/* check if the content of spe_stop_info_t structure has an expected
+   value */
+#define check_stop_info(stop_info, expected) \
+  check_stop_info_helper(__FILE__, __LINE__, stop_info, expected)
+extern int check_stop_info_helper(const char *filename, int line,
+				  const spe_stop_info_t *stop_info,
+				  const spe_stop_info_t *expected);
+/* check if the stop reason is SPE_EXIT and the exit code is an
+   expected value. */
+#define check_exit_code(stop_info, expected) \
+  check_exit_code_helper(__FILE__, __LINE__, stop_info, expected)
+extern int check_exit_code_helper(const char *filename, int line,
+				  const spe_stop_info_t *stop_info,
+				  int expected);
+
+/*
+ * Translating the beginning of the LS as spe_error_info_t structure,
+ * and displays the contents of the structure. This function is
+ * intended to be used in order to print errors on SPE when SPE's
+ * printf is unavailable or unreliable, e.g. while testing printf.
+ */
+extern void print_spe_error_info(spe_context_ptr_t spe);
+
+/* print messages */
+extern int g_verbose_p;
+#define lmessage(f, n, ...) (fprintf(stderr, "%s:%d: ", f, n), fprintf(stderr, __VA_ARGS__))
+#define message(...) lmessage(__FILE__, __LINE__, __VA_ARGS__)
+#define leprintf(...) lmessage(__VA_ARGS__)
+#define eprintf(...) message(__VA_ARGS__)
+#define ltprintf(...) ((void)(g_verbose_p && lmessage(__VA_ARGS__)))
+#define tprintf(...) ((void)(g_verbose_p && message(__VA_ARGS__)))
+
+/* convert enum values into human readable strings */
+extern const char *mbox_behavior_symbol(unsigned int behavior);
+extern const char *proxy_dma_behavior_symbol(unsigned int behavior);
+extern const char *stop_reason_symbol(unsigned int reason);
+extern const char *runtime_error_symbol(unsigned int error);
+extern const char *runtime_exception_symbol(unsigned int exception);
+
+
+/*** file operations ***/
+/* waste file descriptor resource */
+extern int dummy_file_open(int num);
+extern int dummy_file_open_r(int num);
+extern void dummy_file_close(void);
+
+/* generate a unique temporary filename and open it. */
+extern int tmpfile_open(char *name /* at leas 256 bytes */, const char *base);
+
+/* SPUFS direct access.
+   This function is provided only for test purpose.
+   It must *NOT* be used by applications.
+ */
+extern int spufs_open(const spe_context_ptr_t spe, const char *name, int mode);
+
+
+/*** test data ***/
+/* returns a 32-bit random data */
+extern unsigned int rand32(void);
+/* fill buffer with test data
+ *
+ * index and size must be a product of 4.
+ */
+extern void generate_data(void *ptr, unsigned int idx, size_t size);
+
+
+/*** time base ***/
+extern unsigned int get_timebase_frequency(void);
+
+
+/*** barrier ***/
+typedef struct barrier
+{
+  int counter;
+  int done;
+  pthread_mutex_t mutex;
+  pthread_cond_t cond;
+} barrier_t;
+
+#define BARRIER_INITIALIZER {			\
+    .counter = 0, .done = 0,			\
+      .mutex = PTHREAD_MUTEX_INITIALIZER,	\
+      .cond = PTHREAD_COND_INITIALIZER,		\
+      }
+
+extern void barrier_initialize(barrier_t *counter);
+extern void barrier_finalize(barrier_t *counter);
+extern void barrier_sync(barrier_t *counter, int thread_count);
+
+extern void global_sync(int thread_count);
+
+
+/*** multi-threading helpers ***/
+typedef struct ppe_thread ppe_thread_t;
+typedef struct ppe_thread_group
+{
+  ppe_thread_t *threads;
+  int nr_threads;
+  void *data; /* application data */
+} ppe_thread_group_t;
+struct ppe_thread
+{
+  int index;
+  pthread_t thread;
+  ppe_thread_group_t *group;
+};
+/* non-blocking I/F */
+extern ppe_thread_group_t *
+ppe_thread_group_create(size_t num_threads, void *(*proc)(void *), void *data);
+extern int ppe_thread_group_wait(ppe_thread_group_t *group, void **exit_codes);
+/* blocking I/F */
+extern int ppe_thread_group_run(size_t num_threads, void *(*proc)(void *), void *data,
+				void **exit_codes);
+
+#endif /* __PPU_LIBSPE2_TEST_H */
Index: b/tests/ppu_main.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ b/tests/ppu_main.c	2008-03-26 15:32:32.000000000 +0900
@@ -0,0 +1,105 @@
+/*
+ *  libspe2 - A wrapper library to adapt the JSRE SPU usage model to SPUFS
+ *
+ *  Copyright (C) 2008 Sony Computer Entertainment Inc.
+ *  Copyright 2007,2008 Sony Corp.
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library 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
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "ppu_libspe2_test.h"
+
+#define PROGRESS_STEP 1000
+
+int NUM_SPES = DEFAULT_NUM_SPES;
+int g_verbose_p = 0;
+int g_failed;
+
+static void usage(const char *prog)
+{
+  eprintf("Usage: %s [<options>] [--] [<arguments>]\n"
+	  "Options:\n"
+	  "    -h                 print this message\n"
+	  "    -n <iteration>     repeat test <iteration> times\n"
+	  "    -s <SPEs>          # of SPEs\n"
+	  "    -v                 verbose mode\n"
+	  "    -q                 quiet mode\n"
+	  , prog);
+}
+
+int ppu_main(int argc, char **argv, int (*test_proc)(int targc, char **targv))
+{
+  long long i, iteration = 1;
+  char *str;
+  int c;
+
+  /* parse command line options */
+  while ((c = getopt(argc, argv, "hn:vqs:")) != -1) {
+    switch (c) {
+    case 'h':
+      usage(argv[0]);
+      return 0;
+    case 'n':
+      iteration = strtoll(optarg, &str, 0);
+      if (*str) {
+	usage(argv[0]);
+	return 1;
+      }
+      break;
+    case 's':
+      NUM_SPES = strtol(optarg, &str, 0);
+      if (*str) {
+	usage(argv[0]);
+	return 1;
+      }
+      if (NUM_SPES > MAX_SPES) {
+	eprintf("Too many SPEs\n");
+	return 1;
+      }
+      break;
+    case 'v':
+      g_verbose_p = 1;
+      break;
+    case 'q':
+      g_verbose_p = 0;
+      break;
+    default:
+      usage(argv[0]);
+      return 1;
+    }
+  }
+
+  argv[optind - 1] = argv[0]; /* pass argv[0] as the first parameter of test() */
+
+  /* run main test routine in 'iteration' times */
+  for (i = 0; iteration < 0 || i != iteration; i++) {
+    if (i % PROGRESS_STEP == 0) {
+      tprintf("[%lld/%lld]\n", i, iteration);
+    }
+    if ((*test_proc)(argc - optind + 1, argv + optind - 1)) {
+      return 1;
+    }
+    check_failed();
+  }
+
+  tprintf("done\n");
+
+  return 0;
+}
Index: b/tests/ppu_misc.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ b/tests/ppu_misc.c	2008-03-26 15:32:32.000000000 +0900
@@ -0,0 +1,60 @@
+/*
+ *  libspe2 - A wrapper library to adapt the JSRE SPU usage model to SPUFS
+ *
+ *  Copyright (C) 2008 Sony Computer Entertainment Inc.
+ *  Copyright 2008 Sony Corp.
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library 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
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include "ppu_libspe2_test.h"
+
+void generate_data(void *data, unsigned int idx, size_t size)
+{
+  /* index and size must be a product of 4 */
+  unsigned int *ptr = data;
+  unsigned int *end = data + size;
+  unsigned int value = idx / 4;
+
+  while (ptr < end) {
+    *ptr++ = value++;
+  }
+}
+
+unsigned int rand32(void)
+{
+  return rand() ^ (rand() << 16);
+}
+
+unsigned int get_timebase_frequency(void)
+{
+  const char *filename = "/proc/cpuinfo";
+  char buf[256];
+  FILE *fp;
+
+  fp = fopen(filename, "r");
+  if (!fp) {
+    return -1;
+  }
+  while (fgets(buf, sizeof(buf), fp)) {
+    unsigned long long tb;
+    if (sscanf(buf, "timebase%*[ \t]:%llu\n", &tb) == 1) {
+      fclose(fp);
+      return tb;
+    }
+  }
+  fclose(fp);
+  return 0;
+}
Index: b/tests/ppu_result.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ b/tests/ppu_result.c	2008-03-26 15:32:32.000000000 +0900
@@ -0,0 +1,213 @@
+/*
+ *  libspe2 - A wrapper library to adapt the JSRE SPU usage model to SPUFS
+ *
+ *  Copyright (C) 2008 Sony Computer Entertainment Inc.
+ *  Copyright 2008 Sony Corp.
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library 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
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include <string.h>
+
+#include "ppu_libspe2_test.h"
+
+
+/*** checking results and/or printing information ***/
+int check_stop_info_helper(const char *filename, int line,
+			   const spe_stop_info_t *stop_info,
+			   const spe_stop_info_t *expected)
+{
+  if (stop_info->stop_reason != expected->stop_reason) {
+    leprintf(filename, line,
+	     "Unexpected reason: %s (%d)\n",
+	     stop_reason_symbol(stop_info->stop_reason), stop_info->stop_reason);
+    return 1;
+  }
+
+  switch (stop_info->stop_reason) {
+  case SPE_EXIT:
+    if (stop_info->result.spe_exit_code != expected->result.spe_exit_code) {
+      leprintf(filename, line,
+	       "Unexpected exit code: %u (0x%x)\n",
+	       stop_info->result.spe_exit_code, stop_info->result.spe_exit_code);
+      return 1;
+    }
+    break;
+  case SPE_STOP_AND_SIGNAL:
+    if (stop_info->result.spe_signal_code != expected->result.spe_signal_code) {
+      leprintf(filename, line,
+	       "Unexpected signal code: 0x%x\n", stop_info->result.spe_signal_code);
+      return 1;
+    }
+    break;
+  case SPE_RUNTIME_ERROR:
+    if (stop_info->result.spe_runtime_error != expected->result.spe_runtime_error) {
+      leprintf(filename, line,
+	       "Unexpected runtime error: 0x%x (%s)\n",
+	       stop_info->result.spe_runtime_error,
+	       runtime_error_symbol(stop_info->result.spe_runtime_error));
+      return 1;
+    }
+    break;
+  case SPE_RUNTIME_FATAL:
+    if (stop_info->result.spe_runtime_fatal != expected->result.spe_runtime_fatal) {
+      leprintf(filename, line,
+	       "Unexpected errno: %d (%s)\n",
+	       stop_info->result.spe_runtime_fatal,
+	       strerror(stop_info->result.spe_runtime_fatal));
+      return 1;
+    }
+    break;
+  case SPE_RUNTIME_EXCEPTION:
+    if (stop_info->result.spe_runtime_exception != expected->result.spe_runtime_exception) {
+      leprintf(filename, line,
+	       "Unexpected runtime exception: 0x%x (%s)\n",
+	       stop_info->result.spe_runtime_exception,
+	       runtime_exception_symbol(stop_info->result.spe_runtime_exception));
+      return 1;
+    }
+    break;
+  case SPE_CALLBACK_ERROR:
+    if (stop_info->result.spe_callback_error != expected->result.spe_callback_error) {
+      leprintf(filename, line,
+	       "Unexpected callback error: 0x%x\n", stop_info->result.spe_callback_error);
+      return 1;
+    }
+    break;
+  case SPE_ISOLATION_ERROR:
+    if (stop_info->result.spe_isolation_error != expected->result.spe_isolation_error) {
+      leprintf(filename, line,
+	       "Unexpected isolation error: 0x%x\n", stop_info->result.spe_isolation_error);
+      return 1;
+    }
+    break;
+  default:
+    leprintf(filename, line,
+	     "Unknown stop reason: %d\n", stop_info->stop_reason);
+    return 1;
+  }
+
+  return 0;
+}
+
+int check_exit_code_helper(const char *filename, int line,
+			   const spe_stop_info_t *stop_info, int expected_code)
+{
+  spe_stop_info_t expected;
+
+  expected.stop_reason = SPE_EXIT;
+  expected.result.spe_exit_code = expected_code;
+
+  return check_stop_info_helper(filename, line, stop_info, &expected);
+}
+
+void print_spe_error_info(spe_context_ptr_t spe)
+{
+  const void *ls = spe_ls_area_get(spe);
+  const spe_error_info_t *err = (const spe_error_info_t *)ls;
+  if (!err) {
+    tprintf("Could not get LS address. Ignored.\n");
+    return;
+  }
+  fprintf(stderr, "%s:%d: Error in SPE. exit code == %d, errno == %d.\n",
+	  (const char *)ls + err->file, err->line, err->code, err->err);
+}
+
+/*** get human readable strings corresponding to symbols ***/
+const char *mbox_behavior_symbol(unsigned int behavior)
+{
+  switch (behavior) {
+  case SPE_MBOX_ALL_BLOCKING:
+    return "SPE_MBOX_ALL_BLOCKING";
+  case SPE_MBOX_ANY_BLOCKING:
+    return "SPE_MBOX_ANY_BLOCKING";
+  case SPE_MBOX_ANY_NONBLOCKING:
+    return "SPE_MBOX_ANY_NONBLOCKING";
+  default:
+    return "unknown";
+  }
+}
+
+const char *proxy_dma_behavior_symbol(unsigned int behavior)
+{
+  switch (behavior) {
+  case SPE_TAG_ANY:
+    return "SPE_TAG_ANY";
+  case SPE_TAG_ALL:
+    return "SPE_TAG_ALL";
+  case SPE_TAG_IMMEDIATE:
+    return "SPE_TAG_IMMEDIATE";
+  default:
+    return "unknown";
+  }
+}
+
+const char *stop_reason_symbol(unsigned int reason)
+{
+  switch (reason) {
+  case SPE_EXIT:
+    return "SPE_EXIT";
+  case SPE_STOP_AND_SIGNAL:
+    return "SPE_STOP_AND_SIGNAL";
+  case SPE_RUNTIME_ERROR:
+    return "SPE_RUNTIME_ERROR";
+  case SPE_RUNTIME_EXCEPTION:
+    return "SPE_RUNTIME_EXCEPTION";
+  case SPE_RUNTIME_FATAL:
+    return "SPE_RUNTIME_FATAL";
+  case SPE_CALLBACK_ERROR:
+    return "SPE_CALLBACK_ERROR";
+  case SPE_ISOLATION_ERROR:
+    return "SPE_ISOLATION_ERROR";
+  default:
+    return "unknown";
+  }
+}
+
+const char *runtime_error_symbol(unsigned int error)
+{
+  switch (error) {
+  case SPE_SPU_STOPPED_BY_STOP: /* INTERNAL USE ONLY */
+    return "SPE_SPU_STOPPED_BY_STOP";
+  case SPE_SPU_HALT:
+    return "SPE_SPU_HALT";
+  case SPE_SPU_WAITING_ON_CHANNEL: /* INTERNAL USE ONLY */
+    return "SPE_SPU_WAITING_ON_CHANNEL";
+  case SPE_SPU_SINGLE_STEP:
+    return "SPE_SPU_SINGLE_STEP";
+  case SPE_SPU_INVALID_INSTR:
+    return "SPE_SPU_INVALID_INSTR";
+  case SPE_SPU_INVALID_CHANNEL:
+    return "SPE_SPU_INVALID_CHANNEL";
+  default:
+    return "unknown";
+  }
+}
+
+const char *runtime_exception_symbol(unsigned int exception)
+{
+  switch (exception) {
+  case SPE_DMA_ALIGNMENT:
+    return "SPE_DMA_ALIGNMENT";
+  case SPE_DMA_SEGMENTATION:
+    return "SPE_DMA_SEGMENTATION";
+  case SPE_DMA_STORAGE:
+    return "SPE_DMA_STORAGE";
+  case SPE_INVALID_DMA:
+    return "SPE_INVALID_DMA";
+  default:
+    return "unknown";
+  }
+}
Index: b/tests/ppu_thread.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ b/tests/ppu_thread.c	2008-03-26 15:32:32.000000000 +0900
@@ -0,0 +1,141 @@
+/*
+ *  libspe2 - A wrapper library to adapt the JSRE SPU usage model to SPUFS
+ *
+ *  Copyright (C) 2008 Sony Computer Entertainment Inc.
+ *  Copyright 2008 Sony Corp.
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library 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
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include <string.h>
+
+#include "ppu_libspe2_test.h"
+
+
+/*** barriers ***/
+void barrier_initialize(barrier_t *barrier)
+{
+  barrier->counter = 0;
+  barrier->done = 0;
+  pthread_mutex_init(&barrier->mutex, 0);
+  pthread_cond_init(&barrier->cond, 0);
+}
+
+void barrier_finalize(barrier_t *barrier)
+{
+  pthread_cond_destroy(&barrier->cond);
+  pthread_mutex_destroy(&barrier->mutex);
+}
+
+void barrier_sync(barrier_t *barrier, int thread_count)
+{
+  pthread_mutex_lock(&barrier->mutex);
+
+  /* wait until all threads leave the previous sync point */
+  while (barrier->done) {
+    pthread_cond_wait(&barrier->cond, &barrier->mutex);
+  }
+
+  barrier->counter++;
+  if (barrier->counter == thread_count) {
+    /* this thread is the last one which comes to the sync point */
+    barrier->done = thread_count - 1;
+    barrier->counter = 0;
+    pthread_cond_broadcast(&barrier->cond);
+  }
+  else {
+    /* wait until all threads reach the sync point */
+    while (!barrier->done) {
+      pthread_cond_wait(&barrier->cond, &barrier->mutex);
+    }
+
+    ASSERT(barrier->counter == 0);
+
+    barrier->done--;
+    if (barrier->done == 0) {
+      /* this thread is the last one which leave the sync point */
+      pthread_cond_broadcast(&barrier->cond);
+    }
+  }
+
+  pthread_mutex_unlock(&barrier->mutex);
+}
+
+static barrier_t g_barrier = BARRIER_INITIALIZER;
+
+void global_sync(int thread_count)
+{
+  barrier_sync(&g_barrier, thread_count);
+}
+
+/*** multi-threading helpers ***/
+ppe_thread_group_t *ppe_thread_group_create(size_t num_threads,
+					    void *(*proc)(void *), void *data)
+{
+  int i;
+  ppe_thread_group_t *group = malloc(sizeof(ppe_thread_group_t));
+  if (!group) {
+    eprintf("malloc: %s\n", strerror(errno));
+    return NULL;
+  }
+
+  group->threads = calloc(num_threads, sizeof(ppe_thread_t));
+  if (!group->threads) {
+    eprintf("calloc: %s\n", strerror(errno));
+    free(group);
+    return NULL;
+  }
+
+  group->data = data;
+  group->nr_threads = num_threads;
+
+  /* create PPU threads */
+  for (i = 0; i < num_threads; i++) {
+    int ret;
+    group->threads[i].index = i;
+    group->threads[i].group = group;
+    ret = pthread_create(&group->threads[i].thread, NULL, proc, group->threads + i);
+    if (ret) {
+      eprintf("pthread_create: %s\n", strerror(ret));
+      return NULL;
+    }
+  }
+
+  return group;
+}
+
+int ppe_thread_group_wait(ppe_thread_group_t *group, void **exit_codes)
+{
+  int i;
+
+  /* wait for all PPU threads */
+  for (i = 0; i < group->nr_threads; i++) {
+    pthread_join(group->threads[i].thread, exit_codes ? exit_codes + i : NULL);
+  }
+
+  free(group->threads);
+  free(group);
+
+  return 0;
+}
+
+int ppe_thread_group_run(size_t num_threads, void *(*proc)(void *), void *data,
+			 void **exit_codes)
+{
+  ppe_thread_group_t *group = ppe_thread_group_create(num_threads, proc, data);
+  if (!group) return -1;
+
+  return ppe_thread_group_wait(group, exit_codes);
+}
Index: b/tests/spu_libspe2_test.h
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ b/tests/spu_libspe2_test.h	2008-03-26 15:32:32.000000000 +0900
@@ -0,0 +1,81 @@
+/*
+ *  libspe2 - A wrapper library to adapt the JSRE SPU usage model to SPUFS
+ *
+ *  Copyright (C) 2008 Sony Computer Entertainment Inc.
+ *  Copyright 2007,2008 Sony Corp.
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library 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
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+/* This file provides definitions and declarations used by SPEs. */
+
+#ifndef __SPU_LIBSPE2_TEST_H
+#define __SPU_LIBSPE2_TEST_H
+
+#include "common_libspe2_test.h"
+
+#include <spu_intrinsics.h>
+#include <errno.h>
+#include <stdlib.h>
+
+/* Check if data is correct. It's expected that the source data is
+ * created by PPE's 'data_generate' function.
+ *
+ * idx must be a product of 4.
+ * size must be a product of 16.
+ */
+static inline int data_check(unsigned char *p, unsigned int idx, int size)
+{
+  vector unsigned int *pv = (vector unsigned int *)p;
+  vector unsigned int *pv_end = pv + (size >> 4);
+  unsigned int init = idx >> 2;
+  vector unsigned int values = { init, init + 1, init + 2, init + 3, };
+
+  while (pv < pv_end) {
+    if (spu_extract(spu_gather(spu_cmpeq(values, *pv)), 0) != 0xf) {
+      return 0;
+    }
+    values += spu_splats(4U);
+    pv++;
+  }
+  return 1;
+}
+
+/* Spin specified times. */
+static inline void spin(unsigned long long n)
+{
+  volatile unsigned long long i = n;
+  while (i-- > 0) {
+    /* dummy loop */
+  }
+}
+
+/*** To locate the g_spe_error_info at the fixed LS address so that
+ *   the PPE code can access it easily, we define the variable in the
+ *   ".interrupt" section, which always starts at '0'.
+ ***/
+#define DEFINE_SPE_ERROR_INFO \
+  volatile spe_error_info_t g_spe_error_info __attribute__((section(".interrupt")))
+#define DECLARE_SPE_ERROR_INFO extern volatile spe_error_info_t g_spe_error_info
+
+#define error_info_exit(n) do {				 \
+    g_spe_error_info.code = (n);			 \
+    g_spe_error_info.file = (unsigned int)__FILE__;	 \
+    g_spe_error_info.line = __LINE__;			 \
+    g_spe_error_info.err = errno;			 \
+    exit(n);						 \
+  } while (0)
+
+#endif /* __SPU_LIBSPE2_TEST_H */
Index: b/tests/README
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ b/tests/README	2008-03-26 15:32:32.000000000 +0900
@@ -0,0 +1,193 @@
+                             libspe2 test suite
+
+
+1. Introduction
+
+   This is a suite of tests for the SPE runtime management library
+   version 2, aka libspe2. The major purposes of the tests are:
+
+     * function tests of libspe2
+       - checking if the implementation conforms to the spec or not.
+
+     * system tests of libspe2
+       - checking robustness.
+
+     * confirmation of libspe2's usage scenarios
+       - checking if the spec is reasonable or not.
+
+   and in addition to the aboves:
+
+     * system tests of SPUFS
+       - additional tests for SPUFS
+
+
+2. Requirements
+
+   * Hardware
+     - target machine (Cell/B.E. hardware)
+
+   * Runtime environment
+     - Linux kernel with SPUFS
+     - generic userland
+
+   * Software
+     - GNU make
+     - PowerPC or PPU GNU toolchain (gcc or ppu-gcc)
+     - SPU GNU toolchain (spu-gcc)
+     - libspe2 (target of this test suite)
+
+
+3. License
+
+  This test suite is licensed under the terms in the file 'COPYING' in
+  the top directory.
+
+
+4. Running tests
+
+   * To run regular tests, follow the steps below:
+
+     i. Login your target machine.
+
+   (ii. Build the library in the top directory.)
+
+   iii. Run 'make check' in this directory.
+
+   * You can run other tests rather than the regular tests, and also
+     can modify many of test parameters. Type "make help" for details.
+
+
+5. Evaluating results
+
+   * A result of each test is displayed as following:
+
+     <TEST_NAME>: <RESULT>
+
+     If a test passes, the value of <RESULT> is "PASS", otherwise
+     "FAIL".
+
+   * If all (specified) tests pass, a string "PASS" is displayed at
+     the end of output lines and the make command returns zero.
+
+     Otherwise, a string "FAIL" and a list of failed tests are
+     displayed, and the make command returns a non-zero value.
+
+
+6. Adding new test cases
+
+   * Test sets and test cases
+
+     This test suite consists of several test sets, which are groups
+     of test cases. You can add a new test case to the test suite by
+     appending it to one of the existing test sets. You also can
+     define a new test set in the test suite.
+
+   * Adding a new test case to a test set
+
+     To add a new test case to an existing test set, follow the steps
+     below:
+
+     i. Add the file name of the main PPU program of the new test case
+        to the macro '<test-set>_main_progs' in Makefile. The PPU
+        program can be either a script or an ELF executable.
+
+	- The file name is used as the name of the test case.
+
+	  e.g.) If the file name is 'test_my_case.elf', the name of
+	  the test case will be 'test_may_case.elf'.
+
+        - If the test passes, the main PPU program must return zero
+          to the system, otherwise must retun non-zero value.
+
+        - If your test case is an ELF executable, it must have the
+          suffix '.elf'.
+
+        e.g.) If your new test case is 'test_my_case.elf' and you want
+        to add it to the 'regular' test set, modify the macro
+        regular_main_progs in Makefile as:
+
+            regular_main_progs = \
+                    test_my_case.elf \
+                    ...
+
+    ii. If the new test case requires other external PPU executables,
+        add the file name of them to the macro
+        '<test-case>_ppu_progs'.
+
+        - The PPU ELF executables must have the suffix '.elf'.
+
+	- You can use '<test-set>_ppu_progs' macro instead of
+          '<test-case>_ppu_progs', if all test case in the test set
+          require the same external PPU executables.
+
+	e.g.) If the test case 'test_my_case.sh' requires an external
+	helper program 'test_my_case_helper.elf', add the following
+	definition to Makefile:
+
+	    test_my_case.sh_ppu_progs = test_my_case_helper.elf
+
+   iii. If the new test case requires external SPU ELF executables,
+   	i.e. if the test case load the SPU ELF executables by using
+   	the spe_image_open API function, add the file name of them to
+   	the macro '<test-case>_spu_progs'.
+
+        - The SPU executables must have the suffix '.spu.elf'.
+
+	- You can use '<test-set>_spu_progs' macro instead of
+          '<test-case>_spu_progs', if all test case in the test set
+          require the same external executables.
+
+        - It is unnecessary to add embeded SPU programs to the
+          macro (see the step iv).
+
+    iv. Add extra dependencies of the PPU and/or SPU ELF executables.
+
+        - The PPU object files must have the suffix '.o'.
+
+        - The SPU object files must have the suffix '.spu.o'.
+
+        - It is unnecessary to add the main object files which have
+          the same base name as the ELF executables to the extra
+          dependencies.
+
+          e.g.) If the added program is 'test_my_case.spu.elf',
+          you have no need to add 'test_my_case.spu.o' to the
+          dependency of 'test_my_case.spu.elf'.
+
+        - If you want to embed an SPU program into a PPE ELF
+          executable, all you must do is just adding the name of the
+          CESOF file which contains the SPE program to the dependency
+          of the PPE ELF executable.
+
+          o The CESOF files must have the suffix '.embed.o'.
+
+          o The embeded SPU programs can be accessed as
+            'spe_program_handle_t <base-name>' by the PPE ELF
+            executable.
+
+          e.g.) If you want to embed an SPU ELF executable
+          'spu_my_case.spu.elf' into the PPE ELF executable
+          'test_my_case_embed.elf', the definition of the dependency
+          of test_my_case.elf must be:
+
+              test_my_case.elf: spu_my_case.embed.o
+
+          and the SPU program can be accessed as 'spe_program_handle_t
+          spu_my_case'.
+
+     v. Add sources and/or scripts of the test case to this directory.
+
+     	- Sources of ELF executables must be written in C and must
+          have the suffix '.c'.
+
+   * Adding a new test set to the test suite
+
+     You can define a new test set to the test suite as following:
+
+     i. Add the name of the test set to the macro 'test_sets' in
+        Makefile.
+
+    ii. Add test cases to the new test set as above.
+
+---
+EOF
Index: b/tests/testevent1.c
===================================================================
--- a/tests/testevent1.c	2008-03-26 15:32:18.000000000 +0900
+++ b/tests/testevent1.c	2008-03-26 15:32:32.000000000 +0900
@@ -28,7 +28,7 @@ int main()
 	}
 
 	/* load the program. */
-	program = spe_image_open("hello");
+	program = spe_image_open("helloworld.spu.elf");
 	if (!program) {
 		perror("spe_open_image");
 		return -1;
Index: b/tests/testevent2.c
===================================================================
--- a/tests/testevent2.c	2008-03-26 15:32:18.000000000 +0900
+++ b/tests/testevent2.c	2008-03-26 15:32:32.000000000 +0900
@@ -27,7 +27,7 @@ __attribute__((noreturn)) void * spe_thr
 
 	arg_ptr = (struct thread_args *) arg;
 
-	program = spe_image_open("hellointr");
+	program = spe_image_open("hellointr.spu.elf");
 	if (!program) {
 		perror("spe_image_open");
 		pthread_exit(NULL);
Index: b/tests/testlibspe2.c
===================================================================
--- a/tests/testlibspe2.c	2008-03-26 15:32:18.000000000 +0900
+++ b/tests/testlibspe2.c	2008-03-26 15:32:32.000000000 +0900
@@ -33,7 +33,7 @@ int main(void)
     }
 
     printf("Invocation of spe_image_open, context=%p\n", context);
-    if ((program = spe_image_open("testlibspe2hello")) == NULL) {
+    if ((program = spe_image_open("testlibspe2hello.spu.elf")) == NULL) {
         fprintf(stderr,
                 "Invocation of spe_image_open FAILED, context=%p, errno=%d\n",
                 context, errno);
Index: b/tests/testmap1.c
===================================================================
--- a/tests/testmap1.c	2008-03-26 15:32:18.000000000 +0900
+++ b/tests/testmap1.c	2008-03-26 15:32:32.000000000 +0900
@@ -21,4 +21,6 @@ int main(void)
 	spe_context_destroy(ctx);
 	printf("%d done\n", status);
 	printf("%d done\n", MFC_LSA);
+
+	return 0;
 }
Index: b/tests/testmbox.c
===================================================================
--- a/tests/testmbox.c	2008-03-26 15:32:18.000000000 +0900
+++ b/tests/testmbox.c	2008-03-26 15:32:32.000000000 +0900
@@ -29,7 +29,7 @@ __attribute__((noreturn)) void * spe_thr
 
 	arg_ptr = (struct thread_args *) arg;
 
-	program = spe_image_open("readmbox");
+	program = spe_image_open("readmbox.spu.elf");
 	if (!program) {
 		perror("spe_image_open");
 		pthread_exit(NULL);
Index: b/tests/testpthread.c
===================================================================
--- a/tests/testpthread.c	2008-03-26 15:32:18.000000000 +0900
+++ b/tests/testpthread.c	2008-03-26 15:32:32.000000000 +0900
@@ -23,7 +23,7 @@ __attribute__((noreturn)) void * spe_thr
 
 	arg_ptr = (struct thread_args *) arg;
 
-	program = spe_image_open("hello");
+	program = spe_image_open("helloworld.spu.elf");
 	if (!program) {
 		perror("spe_image_open");
 		pthread_exit(NULL);
Index: b/tests/testpthreadmini.c
===================================================================
--- a/tests/testpthreadmini.c	2008-03-26 15:32:18.000000000 +0900
+++ b/tests/testpthreadmini.c	2008-03-26 15:32:32.000000000 +0900
@@ -9,7 +9,7 @@ struct thread_args {
 	void * envp;
 };
 
-void * spe_thread(void * arg)
+static void * spe_thread(void * arg)
 {
 	int flags = 0;
 	unsigned int entry = SPE_DEFAULT_ENTRY;
@@ -18,7 +18,7 @@ void * spe_thread(void * arg)
 
 	arg_ptr = (struct thread_args *) arg;
 
-	program = spe_image_open("hello");
+	program = spe_image_open("helloworld.spu.elf");
 	spe_program_load(arg_ptr->ctx, program);
 	spe_context_run(arg_ptr->ctx, &entry, flags, arg_ptr->argp, arg_ptr->envp, NULL);
 	pthread_exit(NULL);
Index: b/tests/testsingle.c
===================================================================
--- a/tests/testsingle.c	2008-03-26 15:32:18.000000000 +0900
+++ b/tests/testsingle.c	2008-03-26 15:32:32.000000000 +0900
@@ -14,7 +14,7 @@ int main(void)
 	spe_stop_info_t stop_info;
 	int rc;
 	
-	program = spe_image_open("hello");
+	program = spe_image_open("helloworld.spu.elf");
 	if (!program) {
 		perror("spe_open_image");
 		return -1;
Index: b/tests/testsinglemini.c
===================================================================
--- a/tests/testsinglemini.c	2008-03-26 15:32:18.000000000 +0900
+++ b/tests/testsinglemini.c	2008-03-26 15:32:32.000000000 +0900
@@ -11,11 +11,13 @@ int main()
 	void * envp = NULL;
 	spe_program_handle_t * program;
 	
-	program = spe_image_open("hello");
+	program = spe_image_open("helloworld.spu.elf");
 
 	ctx = spe_context_create(flags, 0);
 	spe_program_load(ctx, program);
 	spe_context_run(ctx, &entry, flags, argp, envp, NULL);
 	spe_context_destroy(ctx);
+
+	return 0;
 }
 
Index: b/tests/testinfo.c
===================================================================
--- a/tests/testinfo.c	2008-03-26 15:32:18.000000000 +0900
+++ b/tests/testinfo.c	2008-03-26 15:32:32.000000000 +0900
@@ -21,5 +21,7 @@ int main(void)
 		no = spe_cpu_info_get(SPE_COUNT_USABLE_SPES, i);
 		printf("%2d ==> %d (%d)\n",i, no, errno);
 	}
+
+	return 0;
 }
 



More information about the cbe-oss-dev mailing list