1. Sebastian Bub
  2. Raspberry Pi GPIO Web Control

Commits

Sebastian Bub  committed 0828552

added simple automated tests

  • Participants
  • Parent commits 1eeee21
  • Branches default

Comments (0)

Files changed (5)

File README.md

View file
  • Ignore whitespace
 * Controlling multiple ports in one requests are set one after another, but the code
   is optimized and nothing unnecessary is done in between (it takes about 2-5ms on an idle Raspberry Pi to set all 17 ports, some artificial load (e.g.'find /' in the background) will slow it down to 10-15ms).
 * Cronjobs (exact to the second) for output ports are based on [quartz-scheduler.org](http://quartz-scheduler.org/documentation/quartz-2.1.x/tutorials/crontrigger). Output ports can be set conditionally and you have a simple but powerful semaphore mechanism.
-*   You may define your own variables with a prefix VIRTUAL which are persisted in memory (unknown virtual variables default to "0").
+* You may define your own variables with a prefix VIRTUAL which are persisted in memory (unknown virtual variables default to "0").
 
 ### Planned Features
 
-* Automated tests
 * If GPIO ports are used to represent binary output values, blocking single ports is dangerous: Delayed/Queue requests
 * Custom hooks (pre/post), e.g. for notifications
 * More status and configuration information requestable via json (disengageable)

File src/test/resources/README.md

View file
  • Ignore whitespace
+## Here are all resources for automated tests
+
+The automated tests are only run in simulation mode. Do not change `src/test/resources/gpio.conf` because it's configuration has all different gpio port configurations and is checked from the `src/test/resources/testscript.sh`.
+
+In `start.sh` there is a commented line to be used for configuration.
+
+### Testing
+
+In order to run the test:
+
+* uncomment the testline in `start.sh`
+* start the server
+* run the testscript (it expects a curl in it's $PATH)
+* stop the server
+* (runnint the testscript multiple times will show failures (because of tests of uninitialized values))
+

File src/test/resources/gpio.conf

View file
  • Ignore whitespace
+# Copyright 2012 der-bub.de
+# http://www.der-bub.de
+# Author: Sebastian Bub (sebastian@der-bub.de)
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+#
+# simple configuration file to define handling of GPIO ports
+#
+# use GPIO names here (not RPi connections)
+# http://elinux.org/RPi_BCM2835_GPIOs
+# e.g. GPIO 0 (SDA) is Ping 3
+#
+# - valid values for DIRECTION are IN or OUT or TI
+#   IN: input port
+#   OUT: output port
+#   TI: read analog input. Whenever port is read, the following steps are done:
+#      (During init the port is set as input port)
+#       0. Check that it is not blocked.
+#       1. It is reconfigured to be an output port.
+#       2. It is set to the value of DEFAULT.STATE (required).
+#       3. Wait for the time specified in AUTO.TOGGLE (required).
+#       4. It is reconfigured to be an input port.
+#       5. It is read (in a while loop as fast as possible until a value of (required) not-DEFAULT.STATE is returned.
+#       6. The counter of the while loop is returned (which can be checked with conditions afterwards) or -1
+#          if ti.max.counter is reached.
+#       7. It stays an input port until next read.
+# - choose a name which does not get you in trouble addressing it as a http parameter (umlaut, spaces), e.g. sensor1
+# - if you do not set the default state, it is defined by the OS (default state
+#   is required on auto toggle and TI direction)
+# - auto toggle interval is specified in ms (requires default state), e.g. if you set a gpio, it will automatically
+#   flip to default state after specified time. auto toggle must be smaller than block time
+# - block time is specified in ms, e.g. you can not set the gpio again during  this interval (ensure that user does
+#   not "click multiple times")
+# - choose an appropriate block time for every TI port (or unpredictable things may happen depending on your hardware)
+# - only comment out those ports that you need (as they are set up) on startup (they are exported in sysfs)
+
+# you must set simulate to false for the real world
+simulate.gpios=true
+
+# if direction TI, no of max reads in loop; defaults to 100000 (it is about 2500ms)
+ti.max.counter=100000
+
+###### GPIO.0 = P1-03 #####
+GPIO.0.DIRECTION=OUT
+GPIO.0.NAME=OUTg0d0t250b1000
+GPIO.0.OUT.DEFAULT.STATE=0
+GPIO.0.OUT.AUTO.TOGGLE.TIME=250
+GPIO.0.OUT.BLOCK.TIME=1000
+
+##### GPIO.1 = P1-05 #####
+GPIO.1.DIRECTION=OUT
+GPIO.1.NAME=OUTg1
+#GPIO.1.OUT.DEFAULT.STATE=0
+#GPIO.1.OUT.AUTO.TOGGLE.TIME=250
+#GPIO.1.OUT.BLOCK.TIME=10000
+
+##### GPIO.4 = P1-07 #####
+GPIO.4.DIRECTION=IN
+GPIO.4.NAME=INg4
+#GPIO.4.OUT.DEFAULT.STATE=0
+#GPIO.4.OUT.AUTO.TOGGLE.TIME=250
+#GPIO.4.OUT.BLOCK.TIME=10000
+
+##### GPIO.7 = P1-26 #####
+GPIO.7.DIRECTION=TI
+GPIO.7.NAME=TIg7
+GPIO.7.OUT.DEFAULT.STATE=0
+GPIO.7.OUT.AUTO.TOGGLE.TIME=250
+GPIO.7.OUT.BLOCK.TIME=1000
+
+##### GPIO.8 = P1-24 #####
+GPIO.8.DIRECTION=OUT
+GPIO.8.NAME=OUTg8
+#GPIO.8.OUT.DEFAULT.STATE=0
+#GPIO.8.OUT.AUTO.TOGGLE.TIME=250
+#GPIO.8.OUT.BLOCK.TIME=10000
+
+##### GPIO.9 = P1-21 #####
+#GPIO.9.DIRECTION=OUT
+#GPIO.9.NAME=g9
+#GPIO.9.OUT.DEFAULT.STATE=0
+#GPIO.9.OUT.AUTO.TOGGLE.TIME=250
+#GPIO.9.OUT.BLOCK.TIME=10000
+
+##### GPIO.10 = P1-19 #####
+#GPIO.10.DIRECTION=OUT
+#GPIO.10.NAME=g10
+#GPIO.10.OUT.DEFAULT.STATE=0
+#GPIO.10.OUT.AUTO.TOGGLE.TIME=250
+#GPIO.10.OUT.BLOCK.TIME=10000
+
+##### GPIO.11 = P1-23 #####
+#GPIO.11.DIRECTION=OUT
+#GPIO.11.NAME=g11
+#GPIO.11.OUT.DEFAULT.STATE=0
+#GPIO.11.OUT.AUTO.TOGGLE.TIME=250
+#GPIO.11.OUT.BLOCK.TIME=10000
+
+##### GPIO.14 = P1-08 #####
+#GPIO.14.DIRECTION=OUT
+#GPIO.14.NAME=g14
+#GPIO.14.OUT.DEFAULT.STATE=0
+#GPIO.14.OUT.AUTO.TOGGLE.TIME=250
+#GPIO.14.OUT.BLOCK.TIME=10000
+
+##### GPIO.15 = P1-10 #####
+#GPIO.15.DIRECTION=OUT
+#GPIO.15.NAME=g15
+#GPIO.15.OUT.DEFAULT.STATE=0
+#GPIO.15.OUT.AUTO.TOGGLE.TIME=250
+#GPIO.15.OUT.BLOCK.TIME=10000
+
+##### GPIO.17 = P1-11 #####
+#GPIO.17.DIRECTION=OUT
+#GPIO.17.NAME=g17
+#GPIO.17.OUT.DEFAULT.STATE=0
+#GPIO.17.OUT.AUTO.TOGGLE.TIME=250
+#GPIO.17.OUT.BLOCK.TIME=10000
+
+##### GPIO.18 = P1-12 #####
+#GPIO.18.DIRECTION=OUT
+#GPIO.18.NAME=g18
+#GPIO.18.OUT.DEFAULT.STATE=0
+#GPIO.18.OUT.AUTO.TOGGLE.TIME=250
+#GPIO.18.OUT.BLOCK.TIME=10000
+
+##### GPIO.21 = P1-13 on rev 1.0 #####
+#GPIO.21.DIRECTION=OUT
+#GPIO.21.NAME=g21
+#GPIO.21.OUT.DEFAULT.STATE=0
+#GPIO.21.OUT.AUTO.TOGGLE.TIME=250
+#GPIO.21.OUT.BLOCK.TIME=10000
+
+##### GPIO.22 = P1-15 #####
+#GPIO.22.DIRECTION=OUT
+#GPIO.22.NAME=g22
+#GPIO.22.OUT.DEFAULT.STATE=0
+#GPIO.22.OUT.AUTO.TOGGLE.TIME=250
+#GPIO.22.OUT.BLOCK.TIME=10000
+
+##### GPIO.23 = P1-16 #####
+#GPIO.23.DIRECTION=OUT
+#GPIO.23.NAME=g23
+#GPIO.23.OUT.DEFAULT.STATE=0
+#GPIO.23.OUT.AUTO.TOGGLE.TIME=250
+#GPIO.23.OUT.BLOCK.TIME=10000
+
+##### GPIO.24 = P1-18 #####
+#GPIO.24.DIRECTION=OUT
+#GPIO.24.NAME=g24
+#GPIO.24.OUT.DEFAULT.STATE=0
+#GPIO.24.OUT.AUTO.TOGGLE.TIME=250
+#GPIO.24.OUT.BLOCK.TIME=10000
+
+##### GPIO.25 = P1-22 #####
+#GPIO.25.DIRECTION=OUT
+#GPIO.25.NAME=g25
+#GPIO.25.OUT.DEFAULT.STATE=0
+#GPIO.25.OUT.AUTO.TOGGLE.TIME=250
+#GPIO.25.OUT.BLOCK.TIME=10000
+
+##### GPIO.27 = P1-13 on rev 2.0 #####
+#GPIO.27.DIRECTION=OUT
+#GPIO.27.NAME=g27
+#GPIO.27.OUT.DEFAULT.STATE=0
+#GPIO.27.OUT.AUTO.TOGGLE.TIME=250
+#GPIO.27.OUT.BLOCK.TIME=10000
+

File src/test/resources/testscript.sh

View file
  • Ignore whitespace
+#!/bin/bash
+
+# simple curl test script which must conform to src/test/resources/gpio.conf
+
+# GPIO.0.DIRECTION=OUT
+# GPIO.0.NAME=OUTg0d0t250b1000
+# GPIO.0.OUT.DEFAULT.STATE=0
+# GPIO.0.OUT.AUTO.TOGGLE.TIME=250
+# GPIO.0.OUT.BLOCK.TIME=1000
+#
+# GPIO.1.DIRECTION=OUT
+# GPIO.1.NAME=OUTg1
+#
+# GPIO.4.DIRECTION=IN
+# GPIO.4.NAME=INg4
+#
+# GPIO.7.DIRECTION=TI
+# GPIO.7.NAME=TIg7
+# GPIO.7.OUT.DEFAULT.STATE=0
+# GPIO.7.OUT.AUTO.TOGGLE.TIME=250
+# GPIO.7.OUT.BLOCK.TIME=1000
+
+CURL=curl
+HOST=localhost
+PORT=8080
+
+SUCCESSCOUNTER=0
+FAILURECOUNTER=0
+
+
+singletest() {
+	CMD=$1
+	EXPECTED=$2
+	RESPONSE="`$CURL -s http://$HOST:$PORT/handle?$CMD`"
+	if [ "$RESPONSE" == "$EXPECTED" ]; then
+		echo "SUCCESS for $CMD - was $RESPONSE"
+		SUCCESSCOUNTER=$(( $SUCCESSCOUNTER + 1 ))
+	else
+		echo "FAILED for $CMD - was $RESPONSE --- expected $EXPECTED"
+		FAILURECOUNTER=$(( $FAILURECOUNTER + 1 ))
+	fi
+}
+
+# read unset output port
+singletest 'OUTg1=IN' '{"OUTg1":-1}'
+# set output port
+singletest 'OUTg1=1' '{"OUTg1":1}'
+# read output port
+singletest 'OUTg1=IN' '{"OUTg1":1}'
+# set output port
+singletest 'OUTg1=1' '{"OUTg1":1}'
+# set output port with other value
+singletest 'OUTg1=0' '{"OUTg1":0}'
+# read output port
+singletest 'OUTg1=IN' '{"OUTg1":0}'
+# set output port with other value
+singletest 'OUTg1=1' '{"OUTg1":1}'
+# read unset virtual variable
+singletest 'VIRTUALt1=IN' '{"VIRTUALt1":0}'
+# set virtual variable
+singletest 'VIRTUALt1=1' '{"VIRTUALt1":1}'
+# read virtual variable
+singletest 'VIRTUALt1=IN' '{"VIRTUALt1":1}'
+# set virtual variable other value
+singletest 'VIRTUALt1=0' '{"VIRTUALt1":0}'
+# read virtual variable
+singletest 'VIRTUALt1=IN' '{"VIRTUALt1":0}'
+# conditions on output, set virtual variable
+singletest 'OUTg1==1&VIRTUALt1=1' '{"VIRTUALt1":1}'
+singletest 'OUTg1!=1&VIRTUALt1=1' '{}'
+singletest 'OUTg1!=0&VIRTUALt1=1' '{"VIRTUALt1":1}'
+singletest 'OUTg1>=1&VIRTUALt1=1' '{"VIRTUALt1":1}'
+singletest 'OUTg1>1&VIRTUALt1=1' '{}'
+singletest 'OUTg1<=1&VIRTUALt1=1' '{"VIRTUALt1":1}'
+singletest 'OUTg1<1&VIRTUALt1=1' '{}'
+# conditions on output, set output port
+singletest 'OUTg1==1&OUTg8=1' '{"OUTg8":1}'
+singletest 'OUTg1!=1&OUTg8=1' '{}'
+# conditions on virtual variable, set virtual variable
+singletest 'VIRTUALt1==1&VIRTUALt2=1' '{"VIRTUALt2":1}'
+singletest 'VIRTUALt1!=1&VIRTUALt2=1' '{}'
+# conditions on virtual variable, set output port
+singletest 'VIRTUALt1==1&OUTg8=1' '{"OUTg8":1}'
+singletest 'VIRTUALt1!=1&OUTg8=1' '{}'
+# check blocking time
+singletest 'OUTg0d0t250b1000=1' '{"OUTg0d0t250b1000":1}'
+singletest 'OUTg0d0t250b1000=0' '{"OUTg0d0t250b1000":-2}'
+sleep 1
+singletest 'OUTg0d0t250b1000=0' '{"OUTg0d0t250b1000":0}'
+sleep 1
+# check toggle time
+singletest 'OUTg0d0t250b1000=1' '{"OUTg0d0t250b1000":1}'
+singletest 'OUTg0d0t250b1000=IN' '{"OUTg0d0t250b1000":1}'
+sleep 1
+singletest 'OUTg0d0t250b1000=IN' '{"OUTg0d0t250b1000":0}'
+# write input port
+singletest 'INg4=1' '{"INg4":-1}'
+# read input port (simulation returns 2)
+singletest 'INg4=IN' '{"INg4":2}'
+# conditions on input, set virtual variable
+singletest 'INg4==2&VIRTUALt2=1' '{"VIRTUALt2":1}'
+singletest 'INg4!=2&VIRTUALt2=1' '{}'
+# conditions on input, set output port
+singletest 'INg4==2&OUTg8=1' '{"OUTg8":1}'
+singletest 'INg4!=2&OUTg8=1' '{}'
+
+
+echo "SUCCESS: $SUCCESSCOUNTER - FAILURE: $FAILURECOUNTER"

File start.sh

View file
  • Ignore whitespace
 
 # remote debugging parameter java -Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=5005 \
 
+# for automated testing, overwrite GPIO_CONFIG=src/test/resources/gpio.conf
+
 java \
           -Dlog4j.configuration=$RPI_GPIO_LOG \
           -Dgpio.configuration=$GPIO_CONFIG \