Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| c44b933a83 | |||
| 1f5e9fc502 | |||
| 08231074b9 | |||
| c6d801750e | |||
| 2cf49a8db4 | |||
| 4fba8a8594 |
+3
-3
@@ -19,9 +19,9 @@ set (PROJECT_NAME cameradar)
|
|||||||
|
|
||||||
project (${PROJECT_NAME})
|
project (${PROJECT_NAME})
|
||||||
|
|
||||||
set (${PROJECT_NAME}_VERSION_MAJOR 0)
|
set (${PROJECT_NAME}_VERSION_MAJOR 1)
|
||||||
set (${PROJECT_NAME}_VERSION_MINOR 2)
|
set (${PROJECT_NAME}_VERSION_MINOR 0)
|
||||||
set (${PROJECT_NAME}_VERSION_PATCH 2)
|
set (${PROJECT_NAME}_VERSION_PATCH 0)
|
||||||
set (${PROJECT_NAME}_SUFFIX "-beta")
|
set (${PROJECT_NAME}_SUFFIX "-beta")
|
||||||
set (${PROJECT_NAME}_VERSION "${${PROJECT_NAME}_VERSION_MAJOR}.${${PROJECT_NAME}_VERSION_MINOR}.${${PROJECT_NAME}_VERSION_PATCH}${${PROJECT_NAME}_SUFFIX}")
|
set (${PROJECT_NAME}_VERSION "${${PROJECT_NAME}_VERSION_MAJOR}.${${PROJECT_NAME}_VERSION_MINOR}.${${PROJECT_NAME}_VERSION_PATCH}${${PROJECT_NAME}_SUFFIX}")
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,10 @@
|
|||||||
|
|
||||||
## An RTSP surveillance camera access multitool
|
## An RTSP surveillance camera access multitool
|
||||||
|
|
||||||
|
[](#license)
|
||||||
|
[](https://github.com/EtixLabs/cameradar/releases/latest)
|
||||||
|
|
||||||
|
|
||||||
#### Cameradar allows you to:
|
#### Cameradar allows you to:
|
||||||
|
|
||||||
* **Detect open RTSP hosts** on any accessible subnetwork
|
* **Detect open RTSP hosts** on any accessible subnetwork
|
||||||
@@ -42,7 +46,7 @@ The quick install uses docker to build Cameradar without polluting your machine
|
|||||||
|
|
||||||
### Dependencies
|
### Dependencies
|
||||||
|
|
||||||
The only dependencies are `docker` and `docker-compose`.
|
The only dependencies are `docker`, `docker-tools`, `git` and `make`.
|
||||||
|
|
||||||
### Five steps guide
|
### Five steps guide
|
||||||
|
|
||||||
@@ -63,6 +67,7 @@ The manual installation is recommended if you want to tweak Cameradar and quickl
|
|||||||
To install Cameradar you will need these packages
|
To install Cameradar you will need these packages
|
||||||
|
|
||||||
* cmake (`cmake`)
|
* cmake (`cmake`)
|
||||||
|
* git (`git`)
|
||||||
* gstreamer1.x (`libgstreamer1.0-dev`)
|
* gstreamer1.x (`libgstreamer1.0-dev`)
|
||||||
* ffmpeg (`ffmpeg`)
|
* ffmpeg (`ffmpeg`)
|
||||||
* libcurl (`libcurl4-openssl-dev`)
|
* libcurl (`libcurl4-openssl-dev`)
|
||||||
|
|||||||
@@ -21,5 +21,5 @@
|
|||||||
// if you're not familiar with Docker, only change the
|
// if you're not familiar with Docker, only change the
|
||||||
// cache_manager_name value
|
// cache_manager_name value
|
||||||
"cache_manager_path" : "../cache_managers",
|
"cache_manager_path" : "../cache_managers",
|
||||||
"cache_manager_name" : "mysql"
|
"cache_manager_name" : "dumb"
|
||||||
}
|
}
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
@@ -6,8 +6,8 @@ cameradar:
|
|||||||
- "./conf:/tmp/conf:ro"
|
- "./conf:/tmp/conf:ro"
|
||||||
- "./cameradar_thumbnails:/tmp/cameradar_thumbnails"
|
- "./cameradar_thumbnails:/tmp/cameradar_thumbnails"
|
||||||
links:
|
links:
|
||||||
- ext_cctv_mysql
|
- mysql
|
||||||
ext_cctv_mysql:
|
mysql:
|
||||||
image: mysql:5.7
|
image: mysql:5.7
|
||||||
environment:
|
environment:
|
||||||
MYSQL_ROOT_PASSWORD: root
|
MYSQL_ROOT_PASSWORD: root
|
||||||
|
|||||||
+7
-1
@@ -27,12 +27,18 @@ echo -e $COL_GREEN"ok"$COL_RESET
|
|||||||
# container. The container has to be linked in docker-compose.yml for cameradar
|
# container. The container has to be linked in docker-compose.yml for cameradar
|
||||||
# to be able to interact with it.
|
# to be able to interact with it.
|
||||||
echo -n "replacing mysql host and port in configuration "
|
echo -n "replacing mysql host and port in configuration "
|
||||||
sed -i s#__MYSQL_ADDR__#ext_cctv_mysql#g $CONF
|
sed -i s#__MYSQL_ADDR__#mysql#g $CONF
|
||||||
|
|
||||||
# Reaplce 3306 with the port of your DB
|
# Reaplce 3306 with the port of your DB
|
||||||
sed -i s#__MYSQL_PORT__#3306#g $CONF
|
sed -i s#__MYSQL_PORT__#3306#g $CONF
|
||||||
echo -e $COL_GREEN"ok"$COL_RESET
|
echo -e $COL_GREEN"ok"$COL_RESET
|
||||||
|
|
||||||
|
echo -n "waiting for mysql to be ready "
|
||||||
|
while ! mysqladmin ping -h"mysql" -P3306 --silent; do
|
||||||
|
sleep 1
|
||||||
|
done
|
||||||
|
echo -e $COL_GREEN"ok"$COL_RESET
|
||||||
|
|
||||||
/cameradar/bin/cameradar -l 1 -c /conf/cameradar.conf.json &
|
/cameradar/bin/cameradar -l 1 -c /conf/cameradar.conf.json &
|
||||||
cameradar_pid=$!
|
cameradar_pid=$!
|
||||||
|
|
||||||
|
|||||||
Vendored
+1
@@ -17,6 +17,7 @@ cmake_minimum_required (VERSION 2.8.1)
|
|||||||
# Lib subdirectory
|
# Lib subdirectory
|
||||||
|
|
||||||
include (jsoncpp)
|
include (jsoncpp)
|
||||||
|
include (boost)
|
||||||
include (mysql_connector)
|
include (mysql_connector)
|
||||||
|
|
||||||
set_directory_properties(PROPERTIES CLEAN_NO_CUSTOM ON)
|
set_directory_properties(PROPERTIES CLEAN_NO_CUSTOM ON)
|
||||||
|
|||||||
@@ -0,0 +1,43 @@
|
|||||||
|
FROM ubuntu:15.10
|
||||||
|
|
||||||
|
MAINTAINER brendan.leglaunec@etixgroup.com
|
||||||
|
|
||||||
|
ENV LD_LIBRARY_PATH="/cctv/libraries"
|
||||||
|
|
||||||
|
# install go
|
||||||
|
RUN apt-get update && apt-get install -y make git wget curl
|
||||||
|
RUN wget https://storage.googleapis.com/golang/go1.6.linux-amd64.tar.gz
|
||||||
|
RUN tar -C /usr/local -xzf go1.6.linux-amd64.tar.gz
|
||||||
|
# set variable env
|
||||||
|
ENV GOPATH=/go
|
||||||
|
ENV PATH=$PATH:/go/bin
|
||||||
|
ENV PATH=$PATH:/usr/local/go/bin
|
||||||
|
ENV LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/lib
|
||||||
|
|
||||||
|
# needed for cameradar
|
||||||
|
RUN apt-get update && apt-get install -y \
|
||||||
|
nmap \
|
||||||
|
libmysqlclient18 \
|
||||||
|
ffmpeg \
|
||||||
|
mysql-client \
|
||||||
|
libgstreamer1.0-dev \
|
||||||
|
gstreamer1.0-plugins-base \
|
||||||
|
gstreamer1.0-plugins-good \
|
||||||
|
libcurl4-openssl-dev
|
||||||
|
|
||||||
|
RUN apt-get install -y psmisc
|
||||||
|
|
||||||
|
ADD cctv_*_Debug_Linux.tar.gz /
|
||||||
|
RUN mv cctv_*_Debug_Linux cctv
|
||||||
|
|
||||||
|
# create cameradaratest folder in go src path
|
||||||
|
RUN mkdir -p /go/src/cameradartest
|
||||||
|
ADD ./conf /conf
|
||||||
|
ADD ./docker/run_cameradartest.sh /run.sh
|
||||||
|
|
||||||
|
# get go deps
|
||||||
|
RUN go get github.com/go-sql-driver/mysql
|
||||||
|
|
||||||
|
RUN mkdir /thumbnails
|
||||||
|
WORKDIR /go/src/cameradartest
|
||||||
|
CMD ["/run.sh"]
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
FROM ubuntu:15.10
|
||||||
|
MAINTAINER brendan.leglaunec@etixgroup.com
|
||||||
|
|
||||||
|
RUN useradd -m vlc; \
|
||||||
|
apt-get update; \
|
||||||
|
apt-get install -y vlc-nox
|
||||||
|
|
||||||
|
RUN sed -i s/geteuid/getppid/g /usr/bin/vlc
|
||||||
|
|
||||||
|
ADD ./docker/screen.png /vlc/screen.png
|
||||||
|
COPY ./docker/run_vlc.sh /start.sh
|
||||||
|
COPY ./etix_rtsp_server /etix_rtsp_server
|
||||||
|
|
||||||
|
EXPOSE 8554
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
{
|
||||||
|
"mysql_db" : {
|
||||||
|
"host" : "0.0.0.0",
|
||||||
|
"port" : 3306,
|
||||||
|
"user": "root",
|
||||||
|
"password": "root",
|
||||||
|
"db_name": "cctv"
|
||||||
|
},
|
||||||
|
"subnets" : "172.16.100.13 localhost",
|
||||||
|
"ports" : "554,8554", // if not specified, default will be 1-65535
|
||||||
|
"rtsp_url_file" : "conf/url.json",
|
||||||
|
"rtsp_ids_file" : "conf/ids.json",
|
||||||
|
"thumbnail_storage_path" : "/ce/que/tu/veux"
|
||||||
|
}
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
{
|
||||||
|
"Output": "cameratest.log.xml",
|
||||||
|
|
||||||
|
"Cameradar" : {
|
||||||
|
"Path": "/home/ullaakut/Work/cctv_server2/cameradar/test/cameradar",
|
||||||
|
"Args": "-l 1 -c tmp_config",
|
||||||
|
"Ports": "554,5554,8554",
|
||||||
|
"IdsPath": "conf/ids.json",
|
||||||
|
"RoutesPath": "conf/url.json",
|
||||||
|
"ThumbPath": "/home/ullaakut/.cctv",
|
||||||
|
"dbHost": "0.0.0.0",
|
||||||
|
"dbPort": 3306,
|
||||||
|
"dbUser": "root",
|
||||||
|
"dbPassword": "root",
|
||||||
|
"dbName": "cctv",
|
||||||
|
"Console": false
|
||||||
|
},
|
||||||
|
"Tests" : [
|
||||||
|
{
|
||||||
|
"address" : "127.0.0.1",
|
||||||
|
"password" : "",
|
||||||
|
"port" : "8554",
|
||||||
|
"route" : "live.sdp",
|
||||||
|
"username" : "",
|
||||||
|
"valid" : true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"address" : "172.16.100.11",
|
||||||
|
"password" : "",
|
||||||
|
"port" : "553",
|
||||||
|
"route" : "live.sdp",
|
||||||
|
"username" : "admin",
|
||||||
|
"valid" : false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"address" : "172.16.100.13",
|
||||||
|
"password" : "",
|
||||||
|
"port" : "554",
|
||||||
|
"route" : "live.sdp",
|
||||||
|
"username" : "admin",
|
||||||
|
"valid" : true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
{
|
||||||
|
"username": [
|
||||||
|
"",
|
||||||
|
"admin",
|
||||||
|
"Admin",
|
||||||
|
"root",
|
||||||
|
"supervisor",
|
||||||
|
"ubnt"
|
||||||
|
],
|
||||||
|
"password" : [
|
||||||
|
"",
|
||||||
|
"admin",
|
||||||
|
"9999",
|
||||||
|
"123456",
|
||||||
|
"pass",
|
||||||
|
"camera",
|
||||||
|
"1234",
|
||||||
|
"12345",
|
||||||
|
"fliradmin",
|
||||||
|
"system",
|
||||||
|
"jvc",
|
||||||
|
"meinsm",
|
||||||
|
"root",
|
||||||
|
"4321",
|
||||||
|
"1111111",
|
||||||
|
"password",
|
||||||
|
"ikwd",
|
||||||
|
"supervisor",
|
||||||
|
"ubnt"
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1,77 @@
|
|||||||
|
{
|
||||||
|
"urls" : [
|
||||||
|
"/",
|
||||||
|
"/1.AMP",
|
||||||
|
"/1/stream1",
|
||||||
|
"/CAM_ID.password.mp2",
|
||||||
|
"/GetData.cgi",
|
||||||
|
"/MediaInput/h264",
|
||||||
|
"/MediaInput/mpeg4",
|
||||||
|
"/VideoInput/1/h264/1",
|
||||||
|
"/access_code",
|
||||||
|
"/access_name_for_stream_1_to_5",
|
||||||
|
"/av0_0",
|
||||||
|
"/av2",
|
||||||
|
"/avn=2",
|
||||||
|
"/axis-media/media.amp",
|
||||||
|
"/cam",
|
||||||
|
"/cam0_0",
|
||||||
|
"/cam0_1",
|
||||||
|
"/cam1/h264",
|
||||||
|
"/cam1/h264/multicast",
|
||||||
|
"/cam1/mjpeg",
|
||||||
|
"/cam1/mpeg4",
|
||||||
|
"/camera.stm",
|
||||||
|
"/ch0",
|
||||||
|
"/ch001.sdp",
|
||||||
|
"/ch0_unicast_firststream",
|
||||||
|
"/ch0_unicast_secondstream",
|
||||||
|
"/channel1",
|
||||||
|
"/h264",
|
||||||
|
"/h264/media.amp",
|
||||||
|
"/image.mpg",
|
||||||
|
"/img/media.sav",
|
||||||
|
"/img/video.asf",
|
||||||
|
"/img/video.sav",
|
||||||
|
"/ioImage/1",
|
||||||
|
"/ipcam.sdp",
|
||||||
|
"/ipcam_h264.sdp",
|
||||||
|
"/live.sdp",
|
||||||
|
"/live/h264",
|
||||||
|
"/live/mpeg4",
|
||||||
|
"/live_mpeg4.sdp",
|
||||||
|
"/livestream",
|
||||||
|
"/livestream/",
|
||||||
|
"/media/media.amp",
|
||||||
|
"/media/video1",
|
||||||
|
"/mjpeg/media.smp",
|
||||||
|
"/mp4",
|
||||||
|
"/mpeg4",
|
||||||
|
"/mpeg4/1/media.amp",
|
||||||
|
"/mpeg4/media.amp",
|
||||||
|
"/mpeg4/media.smp",
|
||||||
|
"/mpeg4unicast",
|
||||||
|
"/mpg4/rtsp.amp",
|
||||||
|
"/multicaststream",
|
||||||
|
"/now.mp4",
|
||||||
|
"/nph-h264.cgi",
|
||||||
|
"/nphMpeg4/g726-640x",
|
||||||
|
"/nphMpeg4/g726-640x480",
|
||||||
|
"/nphMpeg4/nil-320x240",
|
||||||
|
"/play1.sdp",
|
||||||
|
"/play2.sdp",
|
||||||
|
"/rtpvideo1.sdp",
|
||||||
|
"/rtsp_tunnel",
|
||||||
|
"/rtsph264",
|
||||||
|
"/stream1",
|
||||||
|
"/user.pin.mp2",
|
||||||
|
"/user_defined",
|
||||||
|
"/video",
|
||||||
|
"/video.3gp",
|
||||||
|
"/video.mp4",
|
||||||
|
"/video1",
|
||||||
|
"/video1+audio1",
|
||||||
|
"/vis",
|
||||||
|
"/wfov"
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
{
|
||||||
|
"Output": "cameratest.log.xml",
|
||||||
|
"Cameradar" : {
|
||||||
|
"Path": "/cctv/bin/cameradar",
|
||||||
|
"Args": "-l 1 -c tmp_config",
|
||||||
|
"Ports": "554,5554,8554,5548",
|
||||||
|
"IdsPath": "/conf/ids.json",
|
||||||
|
"RoutesPath": "/conf/url.json",
|
||||||
|
"ThumbPath": "/thumbnails",
|
||||||
|
"dbHost": "mysql_cameradar",
|
||||||
|
"dbPort": 3306,
|
||||||
|
"dbUser": "root",
|
||||||
|
"dbPassword": "root",
|
||||||
|
"dbName": "cctv",
|
||||||
|
"Console": false
|
||||||
|
},
|
||||||
|
"Tests" : __CAMERAS__
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
{
|
||||||
|
"username": [
|
||||||
|
"",
|
||||||
|
"admin",
|
||||||
|
"Admin",
|
||||||
|
"root",
|
||||||
|
"supervisor",
|
||||||
|
"ubnt"
|
||||||
|
],
|
||||||
|
"password" : [
|
||||||
|
"",
|
||||||
|
"admin",
|
||||||
|
"9999",
|
||||||
|
"123456",
|
||||||
|
"pass",
|
||||||
|
"camera",
|
||||||
|
"1234",
|
||||||
|
"12345",
|
||||||
|
"fliradmin",
|
||||||
|
"system",
|
||||||
|
"jvc",
|
||||||
|
"meinsm",
|
||||||
|
"root",
|
||||||
|
"4321",
|
||||||
|
"1111111",
|
||||||
|
"password",
|
||||||
|
"ikwd",
|
||||||
|
"supervisor",
|
||||||
|
"ubnt"
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1,77 @@
|
|||||||
|
{
|
||||||
|
"urls" : [
|
||||||
|
"/",
|
||||||
|
"/1.AMP",
|
||||||
|
"/1/stream1",
|
||||||
|
"/CAM_ID.password.mp2",
|
||||||
|
"/GetData.cgi",
|
||||||
|
"/MediaInput/h264",
|
||||||
|
"/MediaInput/mpeg4",
|
||||||
|
"/VideoInput/1/h264/1",
|
||||||
|
"/access_code",
|
||||||
|
"/access_name_for_stream_1_to_5",
|
||||||
|
"/av0_0",
|
||||||
|
"/av2",
|
||||||
|
"/avn=2",
|
||||||
|
"/axis-media/media.amp",
|
||||||
|
"/cam",
|
||||||
|
"/cam0_0",
|
||||||
|
"/cam0_1",
|
||||||
|
"/cam1/h264",
|
||||||
|
"/cam1/h264/multicast",
|
||||||
|
"/cam1/mjpeg",
|
||||||
|
"/cam1/mpeg4",
|
||||||
|
"/camera.stm",
|
||||||
|
"/ch0",
|
||||||
|
"/ch001.sdp",
|
||||||
|
"/ch0_unicast_firststream",
|
||||||
|
"/ch0_unicast_secondstream",
|
||||||
|
"/channel1",
|
||||||
|
"/h264",
|
||||||
|
"/h264/media.amp",
|
||||||
|
"/image.mpg",
|
||||||
|
"/img/media.sav",
|
||||||
|
"/img/video.asf",
|
||||||
|
"/img/video.sav",
|
||||||
|
"/ioImage/1",
|
||||||
|
"/ipcam.sdp",
|
||||||
|
"/ipcam_h264.sdp",
|
||||||
|
"/live.sdp",
|
||||||
|
"/live/h264",
|
||||||
|
"/live/mpeg4",
|
||||||
|
"/live_mpeg4.sdp",
|
||||||
|
"/livestream",
|
||||||
|
"/livestream/",
|
||||||
|
"/media/media.amp",
|
||||||
|
"/media/video1",
|
||||||
|
"/mjpeg/media.smp",
|
||||||
|
"/mp4",
|
||||||
|
"/mpeg4",
|
||||||
|
"/mpeg4/1/media.amp",
|
||||||
|
"/mpeg4/media.amp",
|
||||||
|
"/mpeg4/media.smp",
|
||||||
|
"/mpeg4unicast",
|
||||||
|
"/mpg4/rtsp.amp",
|
||||||
|
"/multicaststream",
|
||||||
|
"/now.mp4",
|
||||||
|
"/nph-h264.cgi",
|
||||||
|
"/nphMpeg4/g726-640x",
|
||||||
|
"/nphMpeg4/g726-640x480",
|
||||||
|
"/nphMpeg4/nil-320x240",
|
||||||
|
"/play1.sdp",
|
||||||
|
"/play2.sdp",
|
||||||
|
"/rtpvideo1.sdp",
|
||||||
|
"/rtsp_tunnel",
|
||||||
|
"/rtsph264",
|
||||||
|
"/stream1",
|
||||||
|
"/user.pin.mp2",
|
||||||
|
"/user_defined",
|
||||||
|
"/video",
|
||||||
|
"/video.3gp",
|
||||||
|
"/video.mp4",
|
||||||
|
"/video1",
|
||||||
|
"/video1+audio1",
|
||||||
|
"/vis",
|
||||||
|
"/wfov"
|
||||||
|
]
|
||||||
|
}
|
||||||
Executable
+107
@@ -0,0 +1,107 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
ports=('8554' '8554' '8554' '8554' '8554' '8554')
|
||||||
|
users=('admin' 'root' 'ubnt' 'Admin' 'supervisor' '')
|
||||||
|
passwords=('admin' 'root' '12345' 'ubnt' 'password' '')
|
||||||
|
routes=('live.sdp' 'live.sdp' 'ch001.sdp' '' 'invalid' 'live_mpeg4.sdp')
|
||||||
|
cams_name_pattern="fake_camera_"
|
||||||
|
|
||||||
|
# json generation variable only
|
||||||
|
json="[\n"
|
||||||
|
first=true
|
||||||
|
# $1 = adress, $2 = port, $3 = path, $4 = usernam $5 = password, $6 = valid
|
||||||
|
function make_json {
|
||||||
|
if [ "$first" = true ] ; then first=false
|
||||||
|
else json="$json,\n"; fi
|
||||||
|
json="$json{"
|
||||||
|
json="$json\"address\":\"$1\","
|
||||||
|
json="$json\"port\":\"$2\","
|
||||||
|
json="$json\"route\":\"$3\","
|
||||||
|
json="$json\"username\":\"$4\","
|
||||||
|
json="$json\"password\":\"$5\","
|
||||||
|
json="$json\"valid\":$6"
|
||||||
|
json="$json}"
|
||||||
|
}
|
||||||
|
|
||||||
|
# $1 = configuration template path
|
||||||
|
function generate_conf {
|
||||||
|
echo "generate configuration"
|
||||||
|
sed s#__CAMERAS__#$json#g $1 > cameradartest.conf.json
|
||||||
|
}
|
||||||
|
|
||||||
|
# $1 = numbers of cameras to generate
|
||||||
|
function start {
|
||||||
|
# Seed random generator
|
||||||
|
RANDOM=$(date +%s)
|
||||||
|
|
||||||
|
# start cameras
|
||||||
|
for (( i=1; i<=$1; i++ )); do
|
||||||
|
name="$cams_name_pattern$i"
|
||||||
|
# random conf
|
||||||
|
conf_idx=$(($RANDOM % ${#ports[@]}))
|
||||||
|
|
||||||
|
# get conf variables
|
||||||
|
port=${ports[$conf_idx]}
|
||||||
|
user=${users[$conf_idx]}
|
||||||
|
passw=${passwords[$conf_idx]}
|
||||||
|
route=${routes[$conf_idx]}
|
||||||
|
is_valid=true
|
||||||
|
|
||||||
|
# if conf_idx = 4 -> invalid conf
|
||||||
|
if [ "$conf_idx" == "4" ] ; then is_valid=false; fi
|
||||||
|
|
||||||
|
docker run -d --name "$name" fake-camera /start.sh "$port" "$user" "$passw" "$route"
|
||||||
|
make_json "$name" "$port" "$route" "$user" "$passw" $is_valid
|
||||||
|
done
|
||||||
|
|
||||||
|
# finalize json
|
||||||
|
json="$json]"
|
||||||
|
echo "$json"
|
||||||
|
}
|
||||||
|
|
||||||
|
function stop {
|
||||||
|
# if no cameras containers are started just exit
|
||||||
|
camera_count="`docker ps -a -q --filter="name=$cams_name_pattern" | wc -l`"
|
||||||
|
if [ "$camera_count" == "0" ]; then
|
||||||
|
echo "error: no cameras started"; exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "stopping and removing $camera_count containers"
|
||||||
|
# docker stop $(docker ps -a -q --filter="name=$cams_name_pattern")
|
||||||
|
docker rm -f $(docker ps -a -q --filter="name=$cams_name_pattern") > /dev/null
|
||||||
|
}
|
||||||
|
|
||||||
|
# need first argument at least
|
||||||
|
if [ "$1" == "" ]; then
|
||||||
|
echo "error: invalid number of argument"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
case $1 in
|
||||||
|
"start")
|
||||||
|
# check if the argument is a number.
|
||||||
|
re='^[0-9]+$'
|
||||||
|
if ! [[ $2 =~ $re ]] ; then
|
||||||
|
echo "error: argument is not a number"; exit 1
|
||||||
|
fi
|
||||||
|
if [[ "$3" == "" ]] ; then
|
||||||
|
echo "error: missing path to the configuration file template"; exit 1
|
||||||
|
fi
|
||||||
|
echo "starting $2 cameras"
|
||||||
|
start $2
|
||||||
|
generate_conf $3
|
||||||
|
;;
|
||||||
|
"stop")
|
||||||
|
echo "stopping all cameras tests"
|
||||||
|
stop
|
||||||
|
;;
|
||||||
|
"help")
|
||||||
|
echo "./gen_cameras.sh start CAMS_NB - start CAMS_NB cameras"
|
||||||
|
echo " stop - stop all started cameras"
|
||||||
|
echo " help - display this help"
|
||||||
|
exit 0
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "invalid test name"
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
Executable
+15
@@ -0,0 +1,15 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
while ! mysqladmin ping -h"mysql_cameradar" -P3306 --silent; do
|
||||||
|
sleep 1
|
||||||
|
done
|
||||||
|
|
||||||
|
ls -alhR /conf
|
||||||
|
cat /etc/hosts
|
||||||
|
|
||||||
|
# build
|
||||||
|
go build
|
||||||
|
# run test
|
||||||
|
./cameradartest /tmp/tests/cameradartest.conf.json
|
||||||
|
|
||||||
|
cp cameratest.log.xml /tmp/tests/
|
||||||
Executable
+16
@@ -0,0 +1,16 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
port=$1
|
||||||
|
user=$2
|
||||||
|
passw=$3
|
||||||
|
route=$4
|
||||||
|
url=""
|
||||||
|
|
||||||
|
# need first argument at least
|
||||||
|
if [ "$2" == "" ]; then
|
||||||
|
url="rtsp://:$port/$route"
|
||||||
|
else
|
||||||
|
url="rtsp://$user:$passw@:$port/$route"
|
||||||
|
fi
|
||||||
|
./etix_rtsp_server -u $s -p $3 -r $4
|
||||||
|
# cvlc /vlc/screen.png -I dummy --sout-keep --no-drop-late-frames --no-skip-frames --image-duration 9999 --sout="#transcode{vcodec=h264,fps=15,venc=x264{preset=ultrafast,tune=zerolatency,keyint=30,bframes=0,ref=1,level=30,profile=baseline,hrd=cbr,crf=20,ratetol=1.0,vbv-maxrate=1200,vbv-bufsize=1200,lookahead=0}}:rtp{sdp=$url}" --sout-all
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 558 KiB |
Executable
BIN
Binary file not shown.
Executable
+58
@@ -0,0 +1,58 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# check if a debug package exist in the current folder
|
||||||
|
if ! ls ./cctv_*_Debug_Linux.tar.gz 1> /dev/null 2>&1; then
|
||||||
|
(echo "no debug package in the current folder"; exit 137)
|
||||||
|
exit 137
|
||||||
|
fi
|
||||||
|
|
||||||
|
cams_name_pattern="fake_camera_"
|
||||||
|
cmd=""
|
||||||
|
|
||||||
|
function make_docker_command {
|
||||||
|
cmd="docker run --rm"
|
||||||
|
|
||||||
|
# start cameras
|
||||||
|
for (( i=1; i<=$1; i++ )); do
|
||||||
|
name="$cams_name_pattern$i"
|
||||||
|
cmd="$cmd --link=\"$name\""
|
||||||
|
done
|
||||||
|
|
||||||
|
# add mysql libk
|
||||||
|
cmd="$cmd --link=\"mysql_cameradar\""
|
||||||
|
# add cameradar srcs
|
||||||
|
cmd="$cmd -v \"`pwd`/src:/go/src/cameradartest\""
|
||||||
|
# add cmaeradar conf
|
||||||
|
cmd="$cmd -v \"`pwd`/:/tmp/tests\""
|
||||||
|
# add container name
|
||||||
|
cmd="$cmd cameradartest"
|
||||||
|
}
|
||||||
|
|
||||||
|
function start_test {
|
||||||
|
make_docker_command $1
|
||||||
|
./docker/gen_cameras.sh start $1 ./docker/cameratest.conf.tmpl.json
|
||||||
|
eval $cmd
|
||||||
|
./docker/gen_cameras.sh stop
|
||||||
|
}
|
||||||
|
|
||||||
|
# build images
|
||||||
|
echo "building docker images"
|
||||||
|
# building fake-camera container
|
||||||
|
docker build -f Dockerfile-camera -t fake-camera .
|
||||||
|
|
||||||
|
# building cameradartest image
|
||||||
|
docker build -t cameradartest .
|
||||||
|
|
||||||
|
# getting mysql
|
||||||
|
echo "starting mysql"
|
||||||
|
docker pull mysql:5.7
|
||||||
|
docker run --name mysql_cameradar -e MYSQL_DATABASE=cctv -e MYSQL_ROOT_PASSWORD=root -d mysql:5.7
|
||||||
|
|
||||||
|
start_test 1
|
||||||
|
start_test 5
|
||||||
|
# start_test 10
|
||||||
|
# start_test 20
|
||||||
|
|
||||||
|
# stop mysql
|
||||||
|
echo "stopping mysql"
|
||||||
|
docker rm -f mysql_cameradar
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (m *manager) parseConfig() bool {
|
||||||
|
// Get config file path
|
||||||
|
confPath := "conf/cameratest.conf.json"
|
||||||
|
av := len(os.Args)
|
||||||
|
if av == 2 {
|
||||||
|
confPath = os.Args[1]
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load config
|
||||||
|
fmt.Printf("Loading config file: %s ... ", confPath)
|
||||||
|
configFile, err := os.Open(confPath)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("\nCan't open config file: %s\n", err)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
dec := json.NewDecoder(configFile)
|
||||||
|
if err = dec.Decode(&m); err != nil {
|
||||||
|
fmt.Printf("\nUnable to deserialize config file: %s\n", err)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
fmt.Println("Configuration file successfully loaded\n")
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"database/sql"
|
||||||
|
_ "github.com/go-sql-driver/mysql"
|
||||||
|
"fmt"
|
||||||
|
"strconv"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (m *manager) dropDB() bool {
|
||||||
|
dsn := m.DB.User + ":" + m.DB.Password + "@" + "tcp(" + m.DB.Host + ":" + strconv.Itoa(m.DB.Port) + ")/" + m.DB.Db_name + "?charset=utf8"
|
||||||
|
db, err := sql.Open("mysql", dsn)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
}
|
||||||
|
defer db.Close()
|
||||||
|
q := "DROP DATABASE cctv;"
|
||||||
|
_, err = db.Exec(q)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
}
|
||||||
|
fmt.Println("------ Dropped CCTV Database -------")
|
||||||
|
return true
|
||||||
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Launch it via goroutine
|
||||||
|
// Start read log of service
|
||||||
|
func getResult(test *[]Result, resultPath string) bool {
|
||||||
|
// Load config
|
||||||
|
resultFile, err := os.Open(resultPath)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("\nCan't open result file: %s\n", err)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
dec := json.NewDecoder(resultFile)
|
||||||
|
if err = dec.Decode(&test); err != nil {
|
||||||
|
fmt.Printf("\nUnable to deserialize result file: %s\n", err)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Launch it via goroutine
|
||||||
|
// Start read log of service
|
||||||
|
func readLog(service *Service, reader io.ReadCloser) {
|
||||||
|
scanner := bufio.NewScanner(reader)
|
||||||
|
for scanner.Scan() {
|
||||||
|
str := scanner.Text()
|
||||||
|
if service.Console {
|
||||||
|
fmt.Printf("[%s] %s\n", service.Path, str)
|
||||||
|
}
|
||||||
|
fmt.Printf("%s\n", str)
|
||||||
|
service.Mutex.Lock()
|
||||||
|
service.Logs = append(service.Logs, str)
|
||||||
|
service.Mutex.Unlock()
|
||||||
|
}
|
||||||
|
if err := scanner.Err(); err != nil {
|
||||||
|
fmt.Printf("[%s] Service failed: %s\n", service.Path, err)
|
||||||
|
}
|
||||||
|
fmt.Printf("Logger of service: [%s] stopped\n", service.Path)
|
||||||
|
service.Active = false
|
||||||
|
}
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
manager := new(manager)
|
||||||
|
defer manager.Stop()
|
||||||
|
|
||||||
|
// Parse conf (streams should already be launched by Jenkins)
|
||||||
|
fmt.Println("--- Initializing Cameradar Test Tool ... ---")
|
||||||
|
if !manager.Init() {
|
||||||
|
fmt.Println("-> Cameradar Test Tool initialization FAILED")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Run tests
|
||||||
|
if !manager.Run() {
|
||||||
|
fmt.Println("-> Cameradar Test Tool FAILED")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write results
|
||||||
|
fmt.Println("--- Writing results... ---")
|
||||||
|
if !manager.WriteResults(*(manager.Result), manager.Config.Output) {
|
||||||
|
fmt.Println("-> Write results FAILED")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
fmt.Println("--- Writing results done ---")
|
||||||
|
}
|
||||||
@@ -0,0 +1,54 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"sync"
|
||||||
|
)
|
||||||
|
|
||||||
|
type manager struct {
|
||||||
|
Config
|
||||||
|
|
||||||
|
Tests []Result
|
||||||
|
Result *TestCase
|
||||||
|
DB mysql_db
|
||||||
|
}
|
||||||
|
|
||||||
|
type Config struct {
|
||||||
|
Cameradar Service `json:"Cameradar"`
|
||||||
|
|
||||||
|
Output string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *manager) Init() bool {
|
||||||
|
fmt.Println("- Parsing")
|
||||||
|
if !m.parseConfig() {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println("- Cleaning content")
|
||||||
|
killService(&m.Config.Cameradar)
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *manager) Run() bool {
|
||||||
|
var wg sync.WaitGroup
|
||||||
|
|
||||||
|
fmt.Println("\n- Launching all tests")
|
||||||
|
var newTest = new(TestCase)
|
||||||
|
newTest.expected = m.Tests
|
||||||
|
if (m.generateConfig(m.Tests, &m.DB)) {
|
||||||
|
m.dropDB()
|
||||||
|
wg.Add(1)
|
||||||
|
go m.invokeTestCase(newTest, &wg)
|
||||||
|
m.Result = newTest
|
||||||
|
}
|
||||||
|
wg.Wait()
|
||||||
|
fmt.Printf("All tests completed\n")
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *manager) Stop() bool {
|
||||||
|
killService(&m.Config.Cameradar)
|
||||||
|
return true
|
||||||
|
}
|
||||||
@@ -0,0 +1,87 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os/exec"
|
||||||
|
"strings"
|
||||||
|
"sync"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Service struct {
|
||||||
|
Path string `json:"Path"`
|
||||||
|
Args string `json:"Args"`
|
||||||
|
Ports string `json:"Ports"`
|
||||||
|
IdsPath string `json:"IdsPath"`
|
||||||
|
RoutesPath string `json:"RoutesPath"`
|
||||||
|
DbHost string `json:"dbHost"`
|
||||||
|
DbPort int `json:"dbPort"`
|
||||||
|
DbUser string `json:"dbUser"`
|
||||||
|
DbPassword string `json:"dbPassword"`
|
||||||
|
DbName string `json:"dbName"`
|
||||||
|
ThumbPath string `json:"ThumbPath"`
|
||||||
|
Console bool `json:"Console"`
|
||||||
|
|
||||||
|
Logs []string
|
||||||
|
Active bool // Based on io.ReadCloser status
|
||||||
|
|
||||||
|
Mutex sync.Mutex
|
||||||
|
cmd *exec.Cmd // Go handler of the service
|
||||||
|
}
|
||||||
|
|
||||||
|
func startService(service *Service) bool {
|
||||||
|
// Launch service
|
||||||
|
args := strings.Fields(service.Args)
|
||||||
|
service.cmd = exec.Command(service.Path, args...)
|
||||||
|
|
||||||
|
handler, err := service.cmd.StdoutPipe()
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
errHandler, err := service.cmd.StderrPipe()
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
// Launch
|
||||||
|
err = service.cmd.Start()
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Printf("Service: [%s] started\n", service.Path)
|
||||||
|
service.Active = true
|
||||||
|
|
||||||
|
// Read service logs and update service status
|
||||||
|
// Set pipes
|
||||||
|
go readLog(service, handler)
|
||||||
|
go readLog(service, errHandler)
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Stop only specified service instance
|
||||||
|
func stopService(service *Service) {
|
||||||
|
service.cmd.Process.Kill()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Kill all instances of specified service
|
||||||
|
func killService(service *Service) {
|
||||||
|
// Sending SIGTERM
|
||||||
|
fmt.Printf("Executing: killall %s\n", service.Path)
|
||||||
|
cmd := exec.Command("killall", service.Path)
|
||||||
|
err := cmd.Run()
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sending SIGABORT, more reliable for VLC
|
||||||
|
sigAbort := []string{service.Path, "-s", "SIGABRT"}
|
||||||
|
fmt.Printf("Executing: killall %s -s SIGABRT\n", service.Path)
|
||||||
|
cmd = exec.Command("killall", sigAbort...)
|
||||||
|
err = cmd.Run()
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,168 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
|
"sync"
|
||||||
|
"time"
|
||||||
|
"net"
|
||||||
|
)
|
||||||
|
|
||||||
|
type mysql_db struct {
|
||||||
|
Host string `json:"host"`
|
||||||
|
Port int `json:"port"`
|
||||||
|
User string `json:"user"`
|
||||||
|
Password string `json:"password"`
|
||||||
|
Db_name string `json:"db_name"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type CameradarConfig struct {
|
||||||
|
Mysql_db mysql_db `json:"mysql_db"`
|
||||||
|
Subnets string `json:"subnets"`
|
||||||
|
Ports string `json:"ports"`
|
||||||
|
Rtsp_url_file string `json:"rtsp_url_file"`
|
||||||
|
Rtsp_ids_file string `json:"rtsp_ids_file"`
|
||||||
|
Thumbnail_storage_path string `json:"thumbnail_storage_path"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Result struct {
|
||||||
|
Address string `json:"address"`
|
||||||
|
Password string `json:"password"`
|
||||||
|
Port string `json:"port"`
|
||||||
|
Route string `json:"route"`
|
||||||
|
Username string `json:"username"`
|
||||||
|
Valid bool `json:"valid,omitempty"`
|
||||||
|
Thumb string `json:"thumbnail_path,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type TestCase struct {
|
||||||
|
expected []Result
|
||||||
|
result []Result
|
||||||
|
time time.Duration
|
||||||
|
ok bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// Invoke the test
|
||||||
|
// Wrap results in a TestResult object
|
||||||
|
func (m *manager) invokeTestCase(testCase *TestCase, wg *sync.WaitGroup) {
|
||||||
|
startTime := time.Now()
|
||||||
|
if m.runTestCase(testCase) {
|
||||||
|
testCase.time = time.Since(startTime)
|
||||||
|
testCase.ok = true
|
||||||
|
fmt.Printf("Test OK in %.6fs\n", testCase.time.Seconds())
|
||||||
|
} else {
|
||||||
|
testCase.time = time.Since(startTime)
|
||||||
|
testCase.ok = false
|
||||||
|
fmt.Printf("Test failed in %.6fs\n", testCase.time.Seconds())
|
||||||
|
}
|
||||||
|
wg.Done()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *manager) runTestCase(test *TestCase) bool {
|
||||||
|
fmt.Printf("Test triggered\n")
|
||||||
|
|
||||||
|
Cameradar := m.Config.Cameradar
|
||||||
|
startService(&Cameradar)
|
||||||
|
|
||||||
|
for Cameradar.Active {
|
||||||
|
time.Sleep(5 * time.Millisecond)
|
||||||
|
}
|
||||||
|
found := 0
|
||||||
|
toFind := len(test.expected)
|
||||||
|
var validResults []Result
|
||||||
|
if getResult(&test.result, "result.json") {
|
||||||
|
// Check all valid resutls that are supposed to match
|
||||||
|
// Add them to the valid results and leave the failed
|
||||||
|
// ones in the expected slice
|
||||||
|
for _, r := range test.result {
|
||||||
|
index := 0
|
||||||
|
r.Valid = true
|
||||||
|
for _, e := range test.expected {
|
||||||
|
e.Thumb = r.Thumb
|
||||||
|
var err error
|
||||||
|
var addr[] string
|
||||||
|
addr, err = net.LookupHost(e.Address)
|
||||||
|
e.Address = addr[0]
|
||||||
|
if e == r {
|
||||||
|
_, err = os.Stat(r.Thumb)
|
||||||
|
if err == nil {
|
||||||
|
fmt.Println("The result of ", r.Address, " is valid and the thumbnails were generated by Cameradar.")
|
||||||
|
found++
|
||||||
|
validResults = Extend(validResults, r)
|
||||||
|
test.expected = append(test.expected[:index], test.expected[index+1:]...)
|
||||||
|
break
|
||||||
|
} else {
|
||||||
|
fmt.Println("The result of ", r.Address, " seemed valid, but the thumbnails could not be generated by Cameradar.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
index++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
index := 0
|
||||||
|
// If the result did not match the expected but it was supposed to fail
|
||||||
|
// Add it to the valid results and remove it from the expected slice
|
||||||
|
for _, e := range test.expected {
|
||||||
|
if !e.Valid {
|
||||||
|
found++
|
||||||
|
validResults = Extend(validResults, e)
|
||||||
|
test.expected = append(test.expected[:index], test.expected[index+1:]...)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
index++
|
||||||
|
}
|
||||||
|
// If we found all the expected results, return true
|
||||||
|
if found == toFind {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
test.result = validResults
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *manager) generateConfig(test []Result, DataBase *mysql_db) bool {
|
||||||
|
var config CameradarConfig
|
||||||
|
var db mysql_db
|
||||||
|
|
||||||
|
db.Host = m.Config.Cameradar.DbHost
|
||||||
|
db.Port = m.Config.Cameradar.DbPort
|
||||||
|
db.User = m.Config.Cameradar.DbUser
|
||||||
|
db.Password = m.Config.Cameradar.DbPassword
|
||||||
|
db.Db_name = m.Config.Cameradar.DbName
|
||||||
|
|
||||||
|
for _, t := range test {
|
||||||
|
if len(config.Subnets) > 0 {
|
||||||
|
config.Subnets += ","
|
||||||
|
}
|
||||||
|
config.Subnets += t.Address
|
||||||
|
}
|
||||||
|
config.Mysql_db = db
|
||||||
|
config.Ports = m.Config.Cameradar.Ports
|
||||||
|
config.Rtsp_url_file = m.Config.Cameradar.RoutesPath
|
||||||
|
config.Rtsp_ids_file = m.Config.Cameradar.IdsPath
|
||||||
|
config.Thumbnail_storage_path = m.Config.Cameradar.ThumbPath
|
||||||
|
b, _ := json.Marshal(config)
|
||||||
|
fmt.Println(string(b))
|
||||||
|
err := ioutil.WriteFile("tmp_config", b, 0644)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
*DataBase = db
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func Extend(slice []Result, element Result) []Result {
|
||||||
|
n := len(slice)
|
||||||
|
if n == cap(slice) {
|
||||||
|
// Slice is full; must grow.
|
||||||
|
// We double its size and add 1, so if the size is zero we still grow.
|
||||||
|
newSlice := make([]Result, len(slice), 2*len(slice)+1)
|
||||||
|
copy(newSlice, slice)
|
||||||
|
slice = newSlice
|
||||||
|
}
|
||||||
|
slice = slice[0 : n+1]
|
||||||
|
slice[n] = element
|
||||||
|
return slice
|
||||||
|
}
|
||||||
@@ -0,0 +1,146 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/xml"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"os"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
////////////////////////////////////////////////
|
||||||
|
// Data declarations
|
||||||
|
|
||||||
|
// JUnitTestSuites is a collection of JUnit test suites.
|
||||||
|
type JUnitTestSuites struct {
|
||||||
|
XMLName xml.Name `xml:"testsuites"`
|
||||||
|
Suites []JUnitTestSuite
|
||||||
|
}
|
||||||
|
|
||||||
|
// JUnitTestSuite is a single JUnit test suite which may contain many
|
||||||
|
// testcases.
|
||||||
|
type JUnitTestSuite struct {
|
||||||
|
Tests int `xml:"tests,attr"`
|
||||||
|
Failures int `xml:"failures,attr"`
|
||||||
|
Time string `xml:"time,attr"`
|
||||||
|
TestCases []JUnitTestCase
|
||||||
|
}
|
||||||
|
|
||||||
|
// JUnitTestCase is a single test case with its result.
|
||||||
|
type JUnitTestCase struct {
|
||||||
|
Message string `xml:"message,attr"`
|
||||||
|
Time string `xml:"time,attr"`
|
||||||
|
Failure *JUnitFailure `xml:"failure,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// JUnitFailure contains data related to a failed test.
|
||||||
|
type JUnitFailure struct {
|
||||||
|
Message string `xml:"message,attr"`
|
||||||
|
Type string `xml:"type,attr"`
|
||||||
|
Contents string `xml:",chardata"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *manager) WriteResults(result TestCase, output string) bool {
|
||||||
|
fmt.Printf("Displaying results...\n")
|
||||||
|
// Write Console report
|
||||||
|
m.writeConsoleReport(result)
|
||||||
|
|
||||||
|
// Write XML report
|
||||||
|
// Open xml
|
||||||
|
file, err := os.OpenFile(output, os.O_RDONLY|os.O_CREATE, 0644)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("Error opening XML: %s\n", err)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
defer file.Close()
|
||||||
|
err = m.writeJUnitReportXML(result, file, output)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("Error writing XML: %s\n", err)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
fmt.Printf("-> JUnit XML report written: %s\n", output)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write tests results under JUnit format on w
|
||||||
|
func (m *manager) writeJUnitReportXML(result TestCase, r io.ReadWriter, output string) error {
|
||||||
|
suites := JUnitTestSuites{}
|
||||||
|
dec := xml.NewDecoder(r)
|
||||||
|
if err := dec.Decode(&suites); err != nil {
|
||||||
|
fmt.Printf("\nUnable to deserialize XML log file: %s\n", err)
|
||||||
|
}
|
||||||
|
ts := JUnitTestSuite{
|
||||||
|
Tests: len(result.result) + len(result.expected),
|
||||||
|
Failures: 0,
|
||||||
|
Time: fmt.Sprintf("%.6f", result.time.Seconds()),
|
||||||
|
TestCases: []JUnitTestCase{},
|
||||||
|
}
|
||||||
|
// Run throught all iterations
|
||||||
|
testCase := JUnitTestCase{
|
||||||
|
Time: fmt.Sprintf("%.6f", result.time.Seconds()),
|
||||||
|
Failure: nil,
|
||||||
|
}
|
||||||
|
if len(result.result) > 0 {
|
||||||
|
testCase.Message = "These streams matched what we expected:"
|
||||||
|
}
|
||||||
|
for _, success := range result.result {
|
||||||
|
testCase.Message += " " + success.Address
|
||||||
|
}
|
||||||
|
if !result.ok {
|
||||||
|
testCase.Failure = &JUnitFailure{
|
||||||
|
Message: "These streams did not match what we expected:",
|
||||||
|
Type: "",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for _, fail := range result.expected {
|
||||||
|
ts.Failures++
|
||||||
|
testCase.Failure.Message += " " + fail.Address
|
||||||
|
}
|
||||||
|
ts.TestCases = append(ts.TestCases, testCase)
|
||||||
|
|
||||||
|
suites.Suites = append(suites.Suites, ts)
|
||||||
|
// Fix indent
|
||||||
|
bytes, err := xml.MarshalIndent(suites, "", "\t")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
// Write in param stream
|
||||||
|
|
||||||
|
w, err := os.OpenFile(output, os.O_WRONLY|os.O_TRUNC, 0644)
|
||||||
|
writer := io.Writer(w)
|
||||||
|
writer.Write(bytes)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *manager) writeConsoleReport(result TestCase) bool {
|
||||||
|
min := 50 * time.Hour
|
||||||
|
max := 0 * time.Second
|
||||||
|
total := 0 * time.Second
|
||||||
|
successCount := 0
|
||||||
|
failureCount := 0
|
||||||
|
if result.ok {
|
||||||
|
successCount++
|
||||||
|
total += result.time
|
||||||
|
if result.time < min {
|
||||||
|
min = result.time
|
||||||
|
}
|
||||||
|
if result.time > max {
|
||||||
|
max = result.time
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
failureCount++
|
||||||
|
}
|
||||||
|
fmt.Println("--- Test summary ---\n")
|
||||||
|
if successCount > 0 {
|
||||||
|
fmt.Printf("Results: %d/%d (%d%%)\n", successCount, successCount+failureCount, successCount*100/(successCount+failureCount))
|
||||||
|
fmt.Printf("Total time: %.6fs\n", total.Seconds())
|
||||||
|
fmt.Printf("Average time: %.6fs\n", total.Seconds()/float64(successCount))
|
||||||
|
fmt.Printf("Min time: %.6fs\n", min.Seconds())
|
||||||
|
fmt.Printf("Max time: %.6fs\n", max.Seconds())
|
||||||
|
} else {
|
||||||
|
fmt.Printf("No test in success\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user