diff --git a/.gitignore b/.gitignore
index 39c8d77..9fa2ac9 100644
--- a/.gitignore
+++ b/.gitignore
@@ -43,3 +43,4 @@ odp_timer_test
 odp_generator
 odp_l2fwd
 doxygen-doc
+results.txt
diff --git a/test/CONTRIBUTING b/test/CONTRIBUTING
new file mode 100644
index 0000000..a3b384a
--- /dev/null
+++ b/test/CONTRIBUTING
@@ -0,0 +1,61 @@
+There are three elements to this test suite.
+
+1. The executable tests & examples built and installed by ODP
+2. The run_all.sh top level script in the odp/test directory that discovers and
+executes the tests
+3. The wrapper scripts located along with each of the test source files.
+
+
+Thus the test structure looks approximately like this
+
+test
+├── api_test
+│   ├── generic_template.sh
+│   ├── Makefile
+│   ├── Makefile.am
+│   ├── Makefile.in
+│   ├── minunit.h
+│   ├── odp_atomic.sh
+│   ├── odp_atomic_test.c
+│   ├── odp_atomic_test.h
+│   ├── odp_buffer
+│   ├── odp_buffer.c
+│   ├── odp_buffer.sh
+│   ├── odp_common.c
+│   ├── odp_common.h
+│   ├── odp_ring.sh
+│   ├── odp_ring_test.c
+│   ├── odp_shm.sh
+│   ├── odp_shm_test.c
+│   ├── odp_shm_test.h
+│   ├── odp_timer_ping.c
+│   └── odp_timer_ping_root.sh
+├── Makefile
+├── Makefile.am
+├── Makefile.in
+├── Makefile.inc
+├── README
+└── run_all.sh
+
+To add a new test its C source file should be added, if it is a pure API test
+that just attempts to validate the functional interface or the members of a
+struct then it should be added in /api_test, if it is a functional test such as
+for crypto it would have its own sub directory under test.
+
+Once this compiles and can be installed it needs a wrapper to call it with all
+its cmd line argument permutations. This is done by crating a bash script with
+the samename as the executable with a .sh suffix.
+
+If there are no comandline permuations then the generic template can be copied
+and renamed.
+For example a new test that compiled and is installed with the name new_test
+would need to have the wrapper created with "cp generic_template.sh new_test.sh"
+and this new file should be present along side new_test.c
+
+If the new test requires root permissions to execute a further rename indicates
+this fact.
+For example "mv new_test.sh new_test_root.sh"
+
+
+
+
diff --git a/test/README b/test/README
index 045f88b..d7fa8c0 100644
--- a/test/README
+++ b/test/README
@@ -1,2 +1,29 @@
 Files in this directory are intended to be terse checks that help ensure
 that the ODP API Implementations all perform identically and to specification.
+
+To run all the tests the path to the executables must be specified.
+To build and install odp to a location other than the normal system install
+location the the path prefix needs to be specified to the configure script
+when building.
+
+To prepare the odp lib and the test binaries:-
+odp/bootstrap
+odp/.configure --prefix=~/install
+make install
+
+The binaries should now be in ~/install/bin
+
+In the odp/test directory all the tests can be executed with the run_all.sh
+script, passing it the location of the installed executables. If you are root
+additional tests can be run, the script will inform you.
+
+cd odp/test
+TEST_PATH=/home/mike/install/bin/ ./run_all.sh
+
+The list of locations that will be searched for test scripts can be controlled
+with TEST_DIR_LIST which defaults to TEST_DIR_LIST="./api_test ../example".
+
+The resuts will be saved in odp/test and the format is a file named
+results_<date & time stamp>.txt
+
+
diff --git a/test/api_test/generic_template.sh b/test/api_test/generic_template.sh
new file mode 100755
index 0000000..afebb15
--- /dev/null
+++ b/test/api_test/generic_template.sh
@@ -0,0 +1,12 @@
+#!/bin/bash
+EXECUTABLE=$(basename $0 .sh)
+RESULT_FILE=$1
+
+if [ ! -n "$TEST_PATH$EXECUTABLE" ]
+then
+    echo Result:fail Have you installed the EXECUTABLE "$TEST_PATH$EXECUTABLE"
+fi
+
+FULL_CASE="$TEST_PATH$EXECUTABLE"
+echo "Calling $FULL_CASE from $0"
+$FULL_CASE >> $RESULT_FILE
diff --git a/test/api_test/odp_atomic.sh b/test/api_test/odp_atomic.sh
new file mode 100755
index 0000000..deef32b
--- /dev/null
+++ b/test/api_test/odp_atomic.sh
@@ -0,0 +1,21 @@
+#!/bin/bash
+EXECUTABLE=$(basename $0 .sh)
+RESULT_FILE=$1
+
+if [[ ! -x "$TEST_PATH$EXECUTABLE" ]]
+then
+    echo "$EXECUTABLE" Result:fail >> $RESULT_FILE
+fi
+
+NUM_CORES=$(grep -c ^processor /proc/cpuinfo)
+
+for CORES in $(seq 1 $NUM_CORES)
+do
+    for TEST_CASE in 1 2 3 4 5 6 7
+    do
+        FULL_CASE="$TEST_PATH$EXECUTABLE -t $TEST_CASE -n $CORES"
+        echo "Calling $FULL_CASE from $0"
+        $FULL_CASE >> $RESULT_FILE
+
+    done
+done
diff --git a/test/api_test/odp_ring.sh b/test/api_test/odp_ring.sh
new file mode 100755
index 0000000..5dc4537
--- /dev/null
+++ b/test/api_test/odp_ring.sh
@@ -0,0 +1,12 @@
+#!/bin/bash
+EXECUTABLE=$(basename $0 .sh)
+RESULT_FILE=$1
+
+if [[ ! -x "$TEST_PATH$EXECUTABLE" ]]
+then
+    echo "$EXECUTABLE" Result:fail >> $RESULT_FILE
+fi
+
+FULL_CASE="$TEST_PATH$EXECUTABLE"
+echo "Calling $FULL_CASE from $0"
+$FULL_CASE >> $RESULT_FILE
diff --git a/test/api_test/odp_shm.sh b/test/api_test/odp_shm.sh
new file mode 100755
index 0000000..82dd56b
--- /dev/null
+++ b/test/api_test/odp_shm.sh
@@ -0,0 +1,13 @@
+#!/bin/bash
+EXECUTABLE=$(basename $0 .sh)
+RESULT_FILE=$1
+
+if [[ ! -x "$TEST_PATH$EXECUTABLE" ]]
+then
+    echo "$EXECUTABLE" Result:fail >> $RESULT_FILE
+fi
+
+FULL_CASE="$TEST_PATH$EXECUTABLE"
+echo "Calling $FULL_CASE from $0"
+$FULL_CASE >> $RESULT_FILE
+
diff --git a/test/api_test/odp_timer_ping_root.sh b/test/api_test/odp_timer_ping_root.sh
new file mode 100755
index 0000000..d566768
--- /dev/null
+++ b/test/api_test/odp_timer_ping_root.sh
@@ -0,0 +1,13 @@
+#!/bin/bash
+EXECUTABLE=$(basename $0 .sh)
+RESULT_FILE=$1
+
+if [[ ! -x "$TEST_PATH$EXECUTABLE" ]]
+then
+    echo "$EXECUTABLE" Result:fail >> $RESULT_FILE
+fi
+
+EXECUTABLE=${EXECUTABLE/_root}
+FULL_CASE="$INSTALL$EXECUTABLE"
+echo "Calling $FULL_CASE from $0"
+$FULL_CASE 127.0.0.1 >> $RESULT_FILE
diff --git a/test/run_all.sh b/test/run_all.sh
new file mode 100755
index 0000000..0f272fd
--- /dev/null
+++ b/test/run_all.sh
@@ -0,0 +1,69 @@
+#!/bin/bash
+
+NOW=$(date +"%m_%d_%Y:%H:%M:%S")
+TEST_DIR_LIST="./api_test ../example"
+
+#discover where the test executables are
+if [  -z "$TEST_PATH" ]
+then
+    echo "Assuming the exeutables are on the PATH"
+    echo "TEST_PATH=<your path> to override"
+else
+
+    if [ ! -d "$TEST_PATH" ]
+    then
+        echo "TEST_PATH spcified as '$TEST_PATH' which does not exist"
+        exit -1
+    fi
+    TEST_PATH=$(readlink -f "$TEST_PATH")
+    TEST_PATH="$TEST_PATH/"
+    echo "Tests binary install path '$TEST_PATH'"
+fi
+
+#find test scripts to run by conctentatng for each TEST_DIR
+echo "Looking for test scripts in $TEST_DIR_LIST"
+for TEST_DIR in $TEST_DIR_LIST
+do
+    TEST_SUITE_LIST=$TEST_SUITE_LIST$(find -L $TEST_DIR  -executable -type f | \
+        egrep "\.sh$" | egrep -v "root.sh$" | grep -v template)
+    TEST_SUITE_LIST=$(tr '\n' ' '<<< $TEST_SUITE_LIST)
+
+    ROOT_TEST_SUITE_LIST=$ROOT_TEST_SUITE_LIST$(find -L $TEST_DIR -executable -type f | \
+        egrep ".*_root.sh$" | grep -v template)
+    ROOT_TEST_SUITE_LIST=$(tr '\n' ' '<<< $ROOT_TEST_SUITE_LIST)
+done
+
+echo "Found $TEST_SUITE_LIST" | tee -a results_$NOW.txt
+
+#Inform the users about the list of tests that require root priveldge
+if [ ! -z "$ROOT_TEST_SUITE_LIST" ]
+then
+    if [ "$UID" -ne 0 ]
+    then
+        echo "Your are NOT root; NOT adding these tests: $ROOT_TEST_SUITE_LIST"
+    else
+        echo "Your are root; adding these tests: $ROOT_TEST_SUITE_LIST"
+        TEST_SUITE_LIST=$TEST_SUITE_LIST $ROOT_TEST_SUITE_LIST
+    fi
+fi
+
+#Start running the tests
+for TEST_SUITE in $TEST_SUITE_LIST
+do
+    echo "Calling $TEST_SUITE from $0" | tee -a results_$NOW.txt
+    $TEST_SUITE  results_$NOW.txt
+done
+
+#parse the results for pass/fail
+echo
+echo RESULT SUMMARY
+grep  '^trying\b' results_$NOW.txt
+grep  'pass\b\|fail\b' results_$NOW.txt
+
+grep  'error\b\|warning\b' results_$NOW.txt
+
+#summary of the results
+COUNT_ARRAY=( $TEST_SUITE_LIST )
+echo Attempted ${#COUNT_ARRAY[@]} test scripts, \
+    each may have had multiple test cases.
+
