diff --git a/CMakeLists.txt b/CMakeLists.txt
index 7bd43ae11299d44d9ef0da06bb42a344d288f70d..d4b42f9dba591f85fd379d0a86a1661621807488 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -107,6 +107,30 @@ target_link_libraries(json-validator
 target_link_libraries(json-validator
     PUBLIC
     libubox)
+
+#testing
+IF(CMAKE_BUILD_TYPE STREQUAL Debug)
+	OPTION(ENABLE_BUILD_TESTS "Build tests" ON)
+	OPTION(ENABLE_VALGRIND_TESTS "Build tests with valgrind" ON)
+ELSE()
+	OPTION(ENABLE_BUILD_TESTS "Build tests" OFF)
+	OPTION(ENABLE_VALGRIND_TESTS "Build tests with valgrind" OFF)
+ENDIF()
+
+IF(ENABLE_BUILD_TESTS)
+	FIND_PACKAGE(CMocka)
+	if(CMOCKA_FOUND)
+		#INCLUDE(CodeCoverage)
+		#APPEND_COVERAGE_COMPILER_FLAGS()
+        #ADD_LIBRARY(${PROJECT_NAME}-api SHARED src/json-validator.cpp src/schema.cpp)
+		MESSAGE("-- Building tests")
+		ENABLE_TESTING()
+		ADD_SUBDIRECTORY(test)
+	ELSE(CMOCKA_FOUND)
+		MESSAGE("-- CMocka not found")
+	ENDIF(CMOCKA_FOUND)
+ENDIF(ENABLE_BUILD_TESTS)
+
 # regex with boost if gcc < 4.9 - default is std::regex
 if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
     if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS "4.9.0")
diff --git a/Dockerfile b/Dockerfile
new file mode 100644
index 0000000000000000000000000000000000000000..1afef4006852e144be2dd606a4a91d04f9f838fc
--- /dev/null
+++ b/Dockerfile
@@ -0,0 +1,175 @@
+FROM ubuntu:16.04
+
+LABEL maintainer="jakob.olsson@iopsys.eu"
+LABEL build="docker build -t iopsys/json-validator ."
+LABEL run="docker run -d --name json-validator --privileged --rm -v ${PWD}:/opt/work -p 2222:22 -e LOCAL_USER_ID=`id -u $USER` iopsys/json-validator:latest"
+LABEL exec="docker exec --user=user -it json-validator bash"
+LABEL stop="docker stop json-validator"
+
+RUN \
+      apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y \
+      # general tools
+      git \
+      cmake \
+      wget \
+      build-essential \
+      lcov \
+      apt-utils \
+      autoconf \
+      automake \
+      pkg-config \
+      libtool \
+      vim \
+      valgrind \
+      gdb \
+      cppcheck \
+      python3 \
+      python3-setuptools \
+      openssh-server \
+      clang-format \
+      sudo \
+      strace \
+      supervisor
+
+# Configure OpenSSH server
+RUN mkdir /var/run/sshd
+RUN echo 'root:root' | chpasswd
+RUN sed -i 's/PermitRootLogin prohibit-password/PermitRootLogin yes/' /etc/ssh/sshd_config
+RUN sed -i 's/PermitEmptyPasswords no/PermitEmptyPasswords yes/' /etc/ssh/sshd_config
+RUN sed 's@session\s*required\s*pam_loginuid.so@session optional pam_loginuid.so@g' -i /etc/pam.d/sshd
+
+# Configure gdb-dashboard
+RUN \
+      easy_install3 pip && \
+      pip3 install Pygments
+RUN wget -P ~ git.io/.gdbinit
+RUN \
+      mkdir ~/.gdbinit.d && \
+      touch ~/.gdbinit.d/init && \
+      echo "dashboard -layout source" >> ~/.gdbinit.d/init && \
+      echo "dashboard source -style context 20" >> ~/.gdbinit.d/init && \
+      echo "dashboard -style syntax_highlighting 'monokai'" >> ~/.gdbinit.d/init
+
+# Install dependent libraries
+RUN \
+      apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y \
+      lua5.1-dev \
+      lua5.1
+      #libjson-c-dev
+
+# Install CMocka
+RUN \
+      git clone --branch cmocka-1.1.1 git://git.cryptomilk.org/projects/cmocka.git && \
+      cd cmocka && \
+      mkdir build && \
+      cd build && \
+      cmake .. && \
+      make && \
+      make install
+
+# Remove cached packages.
+RUN rm -rf /var/lib/apt/lists/*
+
+RUN mkdir /opt/dev
+
+# Install JSON-C
+RUN \
+      cd /opt/dev && \
+      git clone https://github.com/json-c/json-c.git && \
+      cd json-c && \
+      sh autogen.sh && \
+      ./configure && \
+      make && \
+      make install && \
+      sudo ldconfig
+
+# ubox
+RUN \
+      cd /opt/dev && \
+      git clone  git://git.openwrt.org/project/libubox.git && \
+      cd libubox && mkdir build && cd build && \
+      git checkout fd57eea9f37e447814afbf934db626288aac23c4 && \
+      cmake -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_BUILD_TYPE:String="Release" .. && \
+      make -j2 && \
+      make install
+
+# uci
+RUN \
+      cd /opt/dev && \
+      git clone git://nbd.name/uci.git && \
+      cd uci && \
+      git checkout a536e300370cc3ad7b14b052b9ee943e6149ba4d && \
+      cmake -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_BUILD_TYPE:String="Release" -DBUILD_LUA=OFF . && \
+      make -j2 && \
+      make install
+
+# ubus
+RUN \
+      cd /opt/dev && \
+      git clone https://git.openwrt.org/project/ubus.git && \
+      cd ubus && \
+      git checkout 5f87f5480ebf004d735dbf44259d08cf8affd305 && \
+      cmake -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_BUILD_TYPE:String="Release" -DBUILD_LUA=OFF -DBUILD_EXAMPLES=OFF . && \
+      make -j2 && \
+      make install
+
+# rpcd
+RUN \
+      cd /opt/dev && \
+      git clone https://git.openwrt.org/project/rpcd.git && \
+      cd rpcd && \
+      git checkout cfe1e75c91bc1bac82e6caab3e652b0ebee59524 && \
+      cmake -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_BUILD_TYPE:String="Release" -DIWINFO_SUPPORT=NO . && \
+      make -j2 && \
+      make install && \
+      mkdir /usr/lib/rpcd && \
+      cp file.so /usr/lib/rpcd
+
+# nlohmann-json
+RUN \
+     cd /opt/dev && \
+     git clone https://github.com/nlohmann/json.git && \
+     cd json && \
+     git checkout be61ad147000be4802173d0d118fd1b8109b4668 && \
+     mkdir build && \
+     cd build && \
+     cmake .. && \
+     cmake --build . && \
+     sudo make install
+
+RUN \
+     cd /opt/dev && \
+     git clone https://github.com/pboettch/json-schema-validator.git json-schema-validator-cpp && \
+     cd json-schema-validator-cpp && \
+     git checkout 3ec0e69a0bce7524f12a865b153b71d0d7ef2484 && \
+     mkdir build && \
+     cd build && \
+     cmake .. -DBUILD_SHARED_LIBS=ON && \
+     make && \
+     sudo make install && \
+     sudo ldconfig
+
+# json-editor
+RUN \
+      cd /opt/dev && \
+      git clone https://dev.iopsys.eu/iopsys/json-editor.git && \
+      cd json-editor && \
+      git checkout 44b32937a062ec4ffc9f7355841dc94ab6efa50f && \
+      cmake -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_BUILD_TYPE:String="Release" . && \
+      make && \
+      make install
+
+RUN mkdir /etc/config
+
+WORKDIR /opt/work
+
+# Expose ports
+EXPOSE 22
+
+# Prepare supervisor
+RUN mkdir -p /var/log/supervisor
+COPY supervisord.conf /etc/supervisor/conf.d/supervisord.conf
+
+# Start entrypoint
+COPY entrypoint.sh /usr/local/bin/entrypoint.sh
+ENTRYPOINT ["/usr/local/bin/entrypoint.sh"]
diff --git a/cmake/modules/FindCMocka.cmake b/cmake/modules/FindCMocka.cmake
new file mode 100644
index 0000000000000000000000000000000000000000..65e12fdf78517ed260421442a6d901ba64ca420e
--- /dev/null
+++ b/cmake/modules/FindCMocka.cmake
@@ -0,0 +1,26 @@
+#  CMOCKA_FOUND - System has CMocka
+#  CMOCKA_INCLUDE_DIRS - The CMocka include directories
+#  CMOCKA_LIBRARIES - The libraries needed to use CMocka
+#  CMOCKA_DEFINITIONS - Compiler switches required for using CMocka
+
+find_package(PkgConfig QUIET)
+if(PKG_CONFIG_FOUND)
+    pkg_check_modules(PC_CMOCKA QUIET cmocka)
+    set(CMOCKA_DEFINITIONS ${PC_CMOCKA_CFLAGS_OTHER})
+endif()
+
+find_path(CMOCKA_INCLUDE_DIR cmocka.h
+          HINTS ${PC_CMOCKA_INCLUDEDIR} ${PC_CMOCKA_INCLUDE_DIRS}
+          PATH_SUFFIXES cmocka)
+
+find_library(CMOCKA_LIBRARY NAMES cmocka
+             HINTS ${PC_CMOCKA_LIBDIR} ${PC_CMOCKA_LIBRARY_DIRS})
+
+set(CMOCKA_LIBRARIES ${CMOCKA_LIBRARY})
+set(CMOCKA_INCLUDE_DIRS ${CMOCKA_INCLUDE_DIR})
+
+include(FindPackageHandleStandardArgs)
+find_package_handle_standard_args(cmocka  DEFAULT_MSG
+                                  CMOCKA_LIBRARY CMOCKA_INCLUDE_DIR)
+
+mark_as_advanced(CMOCKA_INCLUDE_DIR CMOCKA_LIBRARY)
\ No newline at end of file
diff --git a/entrypoint.sh b/entrypoint.sh
new file mode 100755
index 0000000000000000000000000000000000000000..b288b0361ce838b6428fe30516d3d5eb8042dd78
--- /dev/null
+++ b/entrypoint.sh
@@ -0,0 +1,16 @@
+#!/bin/bash
+
+# Create user
+USER_ID=${LOCAL_USER_ID:-9001}
+useradd --shell /bin/bash -u $USER_ID -G sudo -o -c "" -m user
+adduser --disabled-password user
+export HOME=/home/user
+echo "user ALL = NOPASSWD : ALL" >> /etc/sudoers
+
+# Configure OpenSSH to allow login without password
+sed -i -re 's/^user:[^:]+:/user::/' /etc/passwd /etc/shadow
+pam_config="auth [success=1 default=ignore] pam_unix.so nullok\nauth requisite pam_deny.so\nauth required pam_permit.so"
+sed -i "s/@include common-auth/$pam_config/" /etc/pam.d/sshd
+
+# Start supervisor
+/usr/bin/supervisord -c /etc/supervisor/conf.d/supervisord.conf -l /var/log/supervisord.log -j /var/run/supervisord.pid
diff --git a/supervisord.conf b/supervisord.conf
new file mode 100644
index 0000000000000000000000000000000000000000..76187b403000728df2e15d34197628ac2a683308
--- /dev/null
+++ b/supervisord.conf
@@ -0,0 +1,11 @@
+[supervisord]
+nodaemon=true
+
+[program:ubusd]
+command=/bin/bash -c "/usr/sbin/ubusd"
+
+[program:rpcd]
+command=/bin/bash -c "/usr/sbin/rpcd"
+
+[program:sshd]
+command=/usr/sbin/sshd -D
\ No newline at end of file
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..a4b4fe11f6eac8b6c75189d93bc38650eb7ab5c0
--- /dev/null
+++ b/test/CMakeLists.txt
@@ -0,0 +1,48 @@
+PROJECT(schema_test C)
+
+CMAKE_MINIMUM_REQUIRED(VERSION 3.0)
+INCLUDE_DIRECTORIES ("${PROJECT_SOURCE_DIR}/src")
+INCLUDE_DIRECTORIES ("${PROJECT_SOURCE_DIR}")
+FILE(COPY files DESTINATION .)
+
+find_library(UBUS_LIBRARIES NAMES ubus)
+find_library(JSON_LIBRARIES NAMES json-c)
+#find_library(VALIDATOR_LIBRARIES name json-validator)
+find_library(SCHEMA_VALIDATOR_LIBRARIES name json-schema-validator PATHS /usr/lib)
+
+#message("validator_libraries = " ${VALIDATOR_LIBRARIES})
+#message("schema_validator_libraries = " ${SCHEMA_VALIDATOR_LIBRARIES})
+#message("ubus_libraries = " ${UBUS_LIBRARIES})
+SET(api_tests schema_test)
+FOREACH(test_name IN LISTS api_tests)
+    ADD_EXECUTABLE(${test_name} ${test_name}.c)
+    #target_compile_options(${test_name} PRIVATE -std=gnu11)
+	TARGET_LINK_LIBRARIES(
+		${test_name}
+		${CMOCKA_LIBRARIES}
+		json-validator
+		${LIBUBOX_LIBRARIES}
+		${LIBUCI_LIBRARIES}
+		${UBUS_LIBRARIES}
+		${JSON_LIBRARIES}
+		${LIBWEBSOCKETS_LIBRARIES}
+		#${VALIDATOR_LIBRARIES}
+		${SCHEMA_VALIDATOR_LIBRARIES}
+		pthread
+	)
+	ADD_TEST(NAME ${test_name} COMMAND $<TARGET_FILE:${test_name}>)
+ENDFOREACH(test_name)
+
+IF(ENABLE_VALGRIND_TESTS)
+	FIND_PROGRAM(valgrind_FOUND valgrind)
+	IF(valgrind_FOUND)
+		FOREACH(test_name IN LISTS api_tests)
+			ADD_TEST(${test_name}_valgrind valgrind --leak-check=full
+				--show-reachable=yes --show-leak-kinds=all
+				--errors-for-leak-kinds=all --error-exitcode=1 --num-callers=40
+				 ${CMAKE_BINARY_DIR}/test/${test_name})
+		ENDFOREACH(test_name)
+	ELSE(valgrind_FOUND)
+		MESSAGE("-- Valgrind executable not found! Disabling memory leaks tests")
+	ENDIF(valgrind_FOUND)
+ENDIF(ENABLE_VALGRIND_TESTS)
\ No newline at end of file
diff --git a/test/Makefile b/test/Makefile
deleted file mode 100644
index 0cb0d26bde90de75d8e53af33032a63cd4ca381c..0000000000000000000000000000000000000000
--- a/test/Makefile
+++ /dev/null
@@ -1,15 +0,0 @@
-CC		= g++
-CFLAGS		= -g -Wall -std=c++11
-LIBS		= -ljson-c -ljsonschema-c -ljson-validator -ljson-schema-validator
-OBJS		= test.o
-SRCS		= test.c
-ISRCS		= test.h
-
-all: test
-
-test: ${OBJS}
-	${CC} ${LDFLAGS} -o test ${OBJS} ${LIBS}
-
-clean:
-	rm -f test *.o
-
diff --git a/test/files/input/wifi.ap.stations.failure.json b/test/files/input/wifi.ap.stations.failure.json
new file mode 100644
index 0000000000000000000000000000000000000000..f9d11acc6ebc30939e6138239141642e7bb1d019
--- /dev/null
+++ b/test/files/input/wifi.ap.stations.failure.json
@@ -0,0 +1,3 @@
+{
+    "sta": "11:22:33:44:a5:fg"
+}
\ No newline at end of file
diff --git a/test/files/input/wifi.ap.stations.json b/test/files/input/wifi.ap.stations.json
new file mode 100644
index 0000000000000000000000000000000000000000..26efa2dcc55bfac50a520f08f7cda0a76d0e10e3
--- /dev/null
+++ b/test/files/input/wifi.ap.stations.json
@@ -0,0 +1,3 @@
+{
+    "sta": "11:22:33:44:55:ff"
+}
\ No newline at end of file
diff --git a/test/files/input/wifi.status.json b/test/files/input/wifi.status.json
new file mode 100644
index 0000000000000000000000000000000000000000..2c63c0851048d8f7bff41ecf0f8cee05f52fd120
--- /dev/null
+++ b/test/files/input/wifi.status.json
@@ -0,0 +1,2 @@
+{
+}
diff --git a/test/files/input/wifi.wps.status.failure.json b/test/files/input/wifi.wps.status.failure.json
new file mode 100644
index 0000000000000000000000000000000000000000..1c208d262a3fe77770077490a20cd3f76c7e57e4
--- /dev/null
+++ b/test/files/input/wifi.wps.status.failure.json
@@ -0,0 +1,3 @@
+{
+	"vif":5
+}
diff --git a/test/files/input/wifi.wps.status.json b/test/files/input/wifi.wps.status.json
new file mode 100644
index 0000000000000000000000000000000000000000..683d623e494bfd71dc9b656a74c49be7492722bf
--- /dev/null
+++ b/test/files/input/wifi.wps.status.json
@@ -0,0 +1,3 @@
+{
+	"vif":"wl0"
+}
diff --git a/test/files/output/wifi.start.json b/test/files/output/wifi.start.json
new file mode 100644
index 0000000000000000000000000000000000000000..9e26dfeeb6e641a33dae4961196235bdb965b21b
--- /dev/null
+++ b/test/files/output/wifi.start.json
@@ -0,0 +1 @@
+{}
\ No newline at end of file
diff --git a/test/files/output/wifi.status.failure.json b/test/files/output/wifi.status.failure.json
new file mode 100644
index 0000000000000000000000000000000000000000..c890928978b99bda2459a7cff2f437d67b2615be
--- /dev/null
+++ b/test/files/output/wifi.status.failure.json
@@ -0,0 +1,84 @@
+{
+	"radios": [
+		{
+			"name": "wlan0",
+			"isup": true,
+			"standard": "b,g,n",
+			"country": "DE",
+			"band": "5GHz",
+			"channel": 6,
+			"bandwidth": 20,
+			"noise": -59,
+			"rate": 216,
+			"channels": [
+				1,
+				2,
+				3,
+				4,
+				5,
+				6,
+				7,
+				8,
+				9,
+				10,
+				11,
+				12,
+				13
+			],
+			"accesspoints": [
+				{
+					"ifname": "wlan0",
+					"status": "running",
+					"ssid": "NORRLAND-00E09211193C",
+					"bssid": "00:e0:92:11:19:3e"
+				}
+			],
+			"backhauls": [
+				
+			]
+		},
+		{
+			"name": "wlan2",
+			"isup": true,
+			"standard": "a,n,ac",
+			"country": "DE",
+			"band": "2.4GHz",
+			"channel": 64,
+			"bandwidth": 80,
+			"noise": -68,
+			"rate": 1733,
+			"channels": [
+				36,
+				40,
+				44,
+				48,
+				52,
+				56,
+				60,
+				64,
+				100,
+				104,
+				108,
+				112,
+				116,
+				120,
+				124,
+				128,
+				132,
+				136,
+				140
+			],
+			"accesspoints": [
+				{
+					"ifname": "wlan2",
+					"status": "running",
+					"ssid": "NORRLAND-00E09211193C",
+					"bssid": "00:e0:92:zx:19:3f"
+				}
+			],
+			"backhauls": [
+				
+			]
+		}
+	]
+}
diff --git a/test/files/output/wifi.status.json b/test/files/output/wifi.status.json
new file mode 100644
index 0000000000000000000000000000000000000000..8624b715ab10af482aa751602ed8056450e62090
--- /dev/null
+++ b/test/files/output/wifi.status.json
@@ -0,0 +1,84 @@
+{
+	"radios": [
+		{
+			"name": "wlan0",
+			"isup": true,
+			"standard": "b,g,n",
+			"country": "DE",
+			"band": "2.4GHz",
+			"channel": 6,
+			"bandwidth": 20,
+			"noise": -59,
+			"rate": 216,
+			"channels": [
+				1,
+				2,
+				3,
+				4,
+				5,
+				6,
+				7,
+				8,
+				9,
+				10,
+				11,
+				12,
+				13
+			],
+			"accesspoints": [
+				{
+					"ifname": "wlan0",
+					"status": "running",
+					"ssid": "NORRLAND-00E09211193C",
+					"bssid": "00:e0:92:11:19:3e"
+				}
+			],
+			"backhauls": [
+				
+			]
+		},
+		{
+			"name": "wlan2",
+			"isup": true,
+			"standard": "a,n,ac",
+			"country": "DE",
+			"band": "5GHz",
+			"channel": 64,
+			"bandwidth": 80,
+			"noise": -68,
+			"rate": 1733,
+			"channels": [
+				36,
+				40,
+				44,
+				48,
+				52,
+				56,
+				60,
+				64,
+				100,
+				104,
+				108,
+				112,
+				116,
+				120,
+				124,
+				128,
+				132,
+				136,
+				140
+			],
+			"accesspoints": [
+				{
+					"ifname": "wlan2",
+					"status": "running",
+					"ssid": "NORRLAND-00E09211193C",
+					"bssid": "00:e0:92:ff:19:ff"
+				}
+			],
+			"backhauls": [
+				
+			]
+		}
+	]
+}
diff --git a/test/schema_test.c b/test/schema_test.c
new file mode 100644
index 0000000000000000000000000000000000000000..eddaa74403da4cf4eebf5eebb2fc223cc43e5a57
--- /dev/null
+++ b/test/schema_test.c
@@ -0,0 +1,192 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <setjmp.h>
+#include <cmocka.h>
+#include <json-c/json.h>
+#include <libubox/blobmsg_json.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+#include <json-editor.h>
+
+#include "json-validator.h"
+//#include "schema.h"
+
+int cp(const char *to, const char *from)
+{
+    int fd_to, fd_from;
+    char buf[4096];
+    ssize_t nread;
+    int saved_errno;
+
+    fd_from = open(from, O_RDONLY);
+    if (fd_from < 0)
+        return -1;
+
+    fd_to = open(to, O_WRONLY | O_CREAT | O_EXCL, 0666);
+    if (fd_to < 0)
+        goto out_error;
+
+    while (nread = read(fd_from, buf, sizeof buf), nread > 0) {
+        char *out_ptr = buf;
+        ssize_t nwritten;
+
+        do {
+            nwritten = write(fd_to, out_ptr, nread);
+
+            if (nwritten >= 0) {
+                nread -= nwritten;
+                out_ptr += nwritten;
+            } else if (errno != EINTR) {
+                goto out_error;
+            }
+        } while (nread > 0);
+    }
+
+    if (nread == 0) {
+        if (close(fd_to) < 0) {
+            fd_to = -1;
+            goto out_error;
+        }
+        close(fd_from);
+
+        /* Success! */
+        return 0;
+    }
+
+out_error:
+    saved_errno = errno;
+
+    close(fd_from);
+    if (fd_to >= 0)
+        close(fd_to);
+
+    errno = saved_errno;
+    return -1;
+}
+
+
+/* A test case that does nothing and succeeds. */
+static void null_test_success(void **state) {
+	(void) state; /* unused */
+}
+
+static void test_validator_create_nothing(void **state)
+{
+	(void) state; /* unused */
+
+    schema_validator_init();
+
+    schema_validator_destroy();
+}
+
+static void test_validator_create(void **state)
+{
+	(void) state; /* unused */
+
+    schema_validator_init();
+
+    schema_validator_destroy();
+}
+
+static void test_validate_input_document_jobj(void **state)
+{
+	(void) state; /* unused */
+    struct json_object *doc;
+    bool validated;
+
+    schema_validator_init();
+
+    doc = json_object_from_file("/opt/work/test/files/input/wifi.status.json");
+    printf("%s %d doc = %s\n", __func__, __LINE__, json_object_get_string(doc));
+    validated = schema_validator_validate_jobj(doc, "wifi", "status", SCHEMA_INPUT_CALL);
+    assert_true(validated);
+    json_object_put(doc);
+
+    doc = json_object_from_file("/opt/work/test/files/input/wifi.wps.status.json");
+    printf("%s %d doc = %s\n", __func__, __LINE__, json_object_get_string(doc));
+    validated = schema_validator_validate_jobj(doc, "wifi.wps", "status", SCHEMA_INPUT_CALL);
+    assert_true(validated);
+    json_object_put(doc);
+
+    doc = json_object_from_file("/opt/work/test/files/input/wifi.wps.status.failure.json");
+    printf("%s %d doc = %s\n", __func__, __LINE__, json_object_get_string(doc));
+    validated = schema_validator_validate_jobj(doc, "wifi.wps", "status", SCHEMA_INPUT_CALL);
+    assert_false(validated);
+    json_object_put(doc);
+
+    doc = json_object_from_file("/opt/work/test/files/input/wifi.ap.stations.json");
+    printf("%s %d doc = %s\n", __func__, __LINE__, json_object_get_string(doc));
+    validated = schema_validator_validate_jobj(doc, "wifi.ap.wlan2", "stations", SCHEMA_INPUT_CALL);
+    assert_true(validated);
+    json_object_put(doc);
+
+    doc = json_object_from_file("/opt/work/test/files/input/wifi.ap.stations.failure.json");
+    printf("%s %d doc = %s\n", __func__, __LINE__, json_object_get_string(doc));
+    validated = schema_validator_validate_jobj(doc, "wifi.ap.wlan2", "stations", SCHEMA_INPUT_CALL);
+    assert_false(validated);
+    json_object_put(doc);
+
+    schema_validator_destroy();
+}
+
+
+static void test_validate_output_document_jobj(void **state)
+{
+    struct json_object *doc;
+    bool validated;
+
+    schema_validator_init();
+
+    doc = json_object_from_file("/opt/work/test/files/output/wifi.status.json");
+    printf("%s %d doc = %s\n", __func__, __LINE__, json_object_get_string(doc));
+    validated = schema_validator_validate_jobj(doc, "wifi", "status", SCHEMA_OUTPUT_CALL);
+    assert_true(validated);
+    json_object_put(doc);
+
+    doc = json_object_from_file("/opt/work/test/files/output/wifi.status.failure.json");
+    printf("%s %d doc = %s\n", __func__, __LINE__, json_object_get_string(doc));
+    validated = schema_validator_validate_jobj(doc, "wifi", "status", SCHEMA_OUTPUT_CALL);
+    assert_false(validated);
+    json_object_put(doc);
+
+    doc = json_object_from_file("/opt/work/test/files/output/wifi.start.json");
+    printf("%s %d doc = %s\n", __func__, __LINE__, json_object_get_string(doc));
+    validated = schema_validator_validate_jobj(doc, "wifi.wps", "start", SCHEMA_OUTPUT_CALL);
+    assert_true(validated);
+    json_object_put(doc);
+
+    schema_validator_destroy();
+}
+
+static int create_setup(void** state) {
+    printf("copy schemas\n");
+	cp("/usr/share/rpcd/schemas/wifi.json", "/opt/work/ubus/wifi.json");
+    cp("/usr/share/rpcd/schemas/wifi.wps.json", "/opt/work/ubus/wifi.wps.json");
+    cp("/usr/share/rpcd/schemas/wifi.radio.json", "/opt/work/ubus/wifi.radio.json");
+    cp("/usr/share/rpcd/schemas/wifi.ap.json", "/opt/work/ubus/wifi.ap.json");
+
+	return 0;
+}
+
+static int create_teardown(void** state) {
+	remove("/usr/share/rpcd/schemas/wifi.json");
+    remove("/usr/share/rpcd/schemas/wifi.wps.json");
+    remove("/usr/share/rpcd/schemas/wifi.radio.json");
+    remove("/usr/share/rpcd/schemas/wifi.ap.json");
+
+	return 0;
+}
+
+
+int main(void) {
+	const struct CMUnitTest tests[] = {
+		cmocka_unit_test(null_test_success),
+		cmocka_unit_test(test_validator_create_nothing),
+        cmocka_unit_test_setup_teardown(test_validator_create, create_setup, create_teardown),
+        cmocka_unit_test_setup_teardown(test_validate_input_document_jobj, create_setup, create_teardown),
+        cmocka_unit_test_setup_teardown(test_validate_output_document_jobj, create_setup, create_teardown),
+	};
+
+	return cmocka_run_group_tests(tests, NULL, NULL);
+}
diff --git a/test/test.c b/test/test.c
deleted file mode 100644
index cfedf627fb336228f0d34b15eccd96567013a7fc..0000000000000000000000000000000000000000
--- a/test/test.c
+++ /dev/null
@@ -1,43 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdbool.h>
-
-#include <json-c/json.h>
-#include <json-validator.h>
-
-int main(int argc, char *argv[])
-{
-    struct json_object *obj = json_tokener_parse(
-        "{\
-            \"test\": \"s\"\
-        }"
-    );
-
-    struct json_object *sch = json_tokener_parse(
-       "{\
-            \"$schema\": \"http://json-schema.org/draft-07/schema#\",\
-            \"$id\": \"http://example.com/root.json\",\
-            \"type\": \"object\",\
-            \"title\": \"The Root Schema\",\
-            \"required\": [\
-                \"test\"\
-            ],\
-            \"properties\": {\
-                \"test\": {\
-                \"type\": \"integer\",\
-                \"title\": \"The Test Schema\",\
-                \"default\": 0,\
-                \"examples\": [\
-                    5\
-                ]\
-                }\
-            }\
-        }"
-    );
-
-    int rv = json_object_validate_schema(obj, sch);
-
-    printf("rv = %d\n", rv);
-
-    return 0;
-}
\ No newline at end of file