Skip to content

Commit fe7a7f0

Browse files
committed
Initial commit
0 parents  commit fe7a7f0

17 files changed

+1232
-0
lines changed

array.bash

+43
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
#!/usr/bin/env bash
2+
3+
# passed array name must be global variable
4+
array::pop() {
5+
local -n arr=$1
6+
local -n target=$2
7+
# shellcheck disable=SC2034
8+
target="${arr[-1]}"
9+
unset "arr[-1]"
10+
}
11+
12+
array::contains() {
13+
local item="$1"
14+
shift
15+
local arr=("$@")
16+
for a in "${arr[@]}";do
17+
if [ "$a" = "$item" ];then
18+
return 0
19+
fi
20+
done
21+
return 1
22+
}
23+
24+
array_test::pop() {
25+
array=(1 2 3 4 5)
26+
array::pop array item
27+
unit::assert_eq "$item" "5"
28+
unit::assert_eq "${array[*]}" "1 2 3 4"
29+
}
30+
31+
array_test::contains() {
32+
array=(1 2 3 4 5)
33+
unit::assert_success array::contains 3 "${array[@]}"
34+
unit::assert_success array::contains 5 "${array[@]}"
35+
unit::assert_success array::contains 1 "${array[@]}"
36+
unit::assert_failed array::contains 0 "${array[@]}"
37+
unit::assert_failed array::contains 12 "${array[@]}"
38+
}
39+
40+
array_test::all() {
41+
unit::test array_test::pop
42+
unit::test array_test::contains
43+
}

daemon.bash

+140
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
#!/usr/bin/env bash
2+
3+
import dirdb
4+
import log
5+
6+
daemon::start() {
7+
local db=$1
8+
local service_name=$2
9+
local cmd=$3
10+
local timeout=${4:-5}
11+
if ! daemon::is_running "$db" "$service_name";then
12+
daemon::_wrapper "$db" "$service_name" "$cmd" &
13+
daemon::wait_for_running "$db" "$service_name" "$timeout"
14+
fi
15+
}
16+
17+
daemon::wait_for_running() {
18+
local db=$1
19+
local service_name=$2
20+
local wait_time=$3
21+
for ((t=0;t<wait_time*5;t++));do
22+
if daemon::is_running "$db" "$service_name";then
23+
return 0
24+
fi
25+
sleep .2
26+
done
27+
return 1
28+
}
29+
30+
daemon::wait_for_stopped() {
31+
local db=$1
32+
local service_name=$2
33+
local wait_time=$3
34+
for ((t=0;t<wait_time*5;t++));do
35+
if ! daemon::is_running "$db" "$service_name";then
36+
return 0
37+
fi
38+
sleep .2
39+
done
40+
return 1
41+
}
42+
43+
daemon::get_running() {
44+
local db=$1
45+
local -n output_var=$2
46+
local known_services
47+
dirdb::list "$db" "services" known_services
48+
output_var=()
49+
for srv in "${known_services[@]}";do
50+
if daemon::is_running "$db" "$srv";then
51+
output_var+=("$srv")
52+
fi
53+
done
54+
}
55+
56+
daemon::_wrapper() {
57+
local db=$1
58+
local service_name=$2
59+
local cmd=$3
60+
dirdb::write "$db" "services/$service_name" "$BASHPID"
61+
log::debug "Started $service_name as $BASHPID"
62+
$cmd
63+
dirdb::delete "$db" "services/$service_name"
64+
}
65+
66+
daemon::is_running() {
67+
local db=$1
68+
local service_name=$2
69+
if dirdb::is_exists "$db" "services/$service_name";then
70+
local pid
71+
pid=$(dirdb::read "$db" "services/$service_name")
72+
if kill -0 "$pid" &> /dev/null;then
73+
return 0
74+
else
75+
dirdb::delete "$db" "services/$service_name"
76+
fi
77+
fi
78+
return 1
79+
}
80+
81+
daemon::stop_all() {
82+
local db=$1
83+
local timeout=${2:-30}
84+
local signal=${3:-INT}
85+
local services=()
86+
daemon::get_running "$db" services
87+
for srv in "${services[@]}";do
88+
daemon::stop "$db" "$srv" "$timeout" "$signal"
89+
done
90+
}
91+
92+
daemon::stop() {
93+
local db=$1
94+
local service_name=$2
95+
local timeout=${3:-30}
96+
local signal=${4:-INT}
97+
if daemon::is_running "$db" "$service_name";then
98+
local pid
99+
pid=$(dirdb::read "$db" "services/$service_name")
100+
log::debug "Killing $service_name($pid) (SIG$signal)"
101+
kill "-$signal" "$pid"
102+
if ! daemon::wait_for_stopped "$db" "$service_name" "$timeout";then
103+
log::debug "killing $service_name($pid) (SIGKILL)"
104+
kill -9 "$pid"
105+
fi
106+
else
107+
log::debug "Service $service_name is not running"
108+
fi
109+
}
110+
111+
daemon_test::_example_task() {
112+
sleep 1m &
113+
wait
114+
}
115+
116+
daemon_test::spawn_and_kill() {
117+
import tmp
118+
119+
local test_db
120+
tmp::create_dir test_db
121+
122+
unit::assert_failed daemon::is_running "$test_db" "example"
123+
local running
124+
daemon::get_running "$test_db" running
125+
unit::assert_eq "${running[*]}" ""
126+
daemon::start "$test_db" "example" daemon_test::_example_task
127+
unit::assert_success daemon::is_running "$test_db" "example"
128+
daemon::get_running "$test_db" running
129+
unit::assert_eq "${running[*]}" "example"
130+
daemon::stop "$test_db" "example"
131+
unit::assert_failed daemon::is_running "$test_db" "example"
132+
daemon::get_running "$test_db" running
133+
unit::assert_eq "${running[*]}" ""
134+
135+
tmp::cleanup
136+
}
137+
138+
daemon_test::all() {
139+
unit::test daemon_test::spawn_and_kill
140+
}

dirdb.bash

+105
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
#!/usr/bin/env bash
2+
3+
dirdb::read() {
4+
local location="$1"
5+
local key="$2"
6+
local default="$3"
7+
8+
local path="$location/$key"
9+
if [ -f "$path" ];then
10+
cat "$path" 2>/dev/null
11+
else
12+
echo -n "$default"
13+
fi
14+
}
15+
16+
dirdb::is_exists() {
17+
local location="$1"
18+
local key="$2"
19+
20+
local path="$location/$key"
21+
if [ -f "$path" ];then
22+
return 0
23+
fi
24+
return 1
25+
}
26+
27+
dirdb::delete() {
28+
local location="$1"
29+
local key="$2"
30+
31+
local path="$location/$key"
32+
33+
if [ -e "$path" ];then
34+
rm -r "$path"
35+
fi
36+
}
37+
38+
dirdb::list() {
39+
local _location="$1"
40+
local _key="$2"
41+
local -n output_list=$3
42+
43+
local _path="$_location/$_key"
44+
output_list=()
45+
if [ -e "$_path" ];then
46+
local _list=( "$_path"/* )
47+
for _item in "${_list[@]}";do
48+
if [ -f "$_item" ];then
49+
output_list+=("${_item##$_path/}")
50+
fi
51+
done
52+
fi
53+
}
54+
55+
dirdb::write() {
56+
local location="$1"
57+
local key="$2"
58+
local value="$3"
59+
60+
local path="$location/$key"
61+
mkdir -p "$( dirname "$path")"
62+
echo -n "$value" > "$path"
63+
}
64+
65+
66+
dirdb_test::test_operations() {
67+
import tmp
68+
local tempdb=""
69+
tmp::create_dir tempdb "dirdb_unit_test"
70+
71+
unit::assert_eq "$(dirdb::read "$tempdb" some/key "default")" "default"
72+
unit::assert_failed dirdb::is_exists "$tempdb" some/key
73+
dirdb::write "$tempdb" some/key "content"
74+
unit::assert_eq "$(dirdb::read "$tempdb" some/key "default")" "content"
75+
unit::assert_success dirdb::is_exists "$tempdb" some/key
76+
dirdb::delete "$tempdb" some/key
77+
unit::assert_eq "$(dirdb::read "$tempdb" some/key "default")" "default"
78+
unit::assert_failed dirdb::is_exists "$tempdb" some/key
79+
80+
tmp::cleanup
81+
}
82+
83+
dirdb_test::test_lists() {
84+
import tmp
85+
local tempdb=""
86+
tmp::create_dir tempdb "dirdb_unit_test"
87+
88+
dirdb::write "$tempdb" list/a "1"
89+
dirdb::write "$tempdb" list/b "2"
90+
local items=""
91+
dirdb::list "$tempdb" list items
92+
unit::assert_eq "${items[*]}" "a b"
93+
dirdb::delete "$tempdb" list
94+
unit::assert_failed dirdb::is_exists "$tempdb" list/a
95+
unit::assert_failed dirdb::is_exists "$tempdb" list/b
96+
dirdb::list "$tempdb" list items
97+
unit::assert_eq "${items[*]}" ""
98+
99+
tmp::cleanup
100+
}
101+
102+
dirdb_test::all() {
103+
unit::test dirdb_test::test_operations
104+
unit::test dirdb_test::test_lists
105+
}

exec.bash

+94
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
#!/bin/usr/env bash
2+
3+
import log
4+
5+
# run command without displaying any output when it success
6+
exec::silent() {
7+
if [ "$DEBUG" = 1 ]; then
8+
"$@"
9+
ret=$?
10+
return $ret
11+
else
12+
local log=""
13+
if ! log="$("$@" 2>&1)";then
14+
log::error "Command $* failed"
15+
log::error "$log"
16+
return 1
17+
fi
18+
19+
return 0
20+
fi
21+
}
22+
23+
exec__sudo_keeping=0
24+
25+
exec::sudo_keep_alive() {
26+
if [ "$exec__sudo_keeping" != "1" ];then
27+
exec__sudo_keeping=1
28+
sudo -v
29+
while true; do sudo -n true; sleep 60; kill -0 "$$" || exit; done 2>/dev/null &
30+
fi
31+
}
32+
33+
exec::is_cmd_available() {
34+
local cmd="$1"
35+
if command -v "$cmd" &>/dev/null;then
36+
return 0
37+
fi
38+
return 1
39+
}
40+
41+
exec::is_fn() {
42+
local fn="$1"
43+
if [ "$(type -t "$fn")" = "function" ];then
44+
return 0
45+
fi
46+
return 1
47+
}
48+
49+
exec::assert_cmd() {
50+
local cmd="$1"
51+
if ! exec::is_cmd_available "$cmd";then
52+
log::panic "Command \`$cmd\` is not available, but is required by this application"
53+
fi
54+
}
55+
56+
exec_test::test_is_cmd_available() {
57+
unit::assert_success "exec::is_cmd_available bash"
58+
unit::assert_failed "exec::is_cmd_available this_for_sure_not_exists_bleh"
59+
}
60+
61+
exec_test::test_output() {
62+
local og_debug="$DEBUG"
63+
DEBUG=0
64+
set +eE
65+
local should_be_silent
66+
should_be_silent=$(exec::silent bash -c 'echo output && true' 2>&1)
67+
unit::assert_eq "$should_be_silent" "" "shouldn't have output on success"
68+
69+
local should_have_output
70+
should_have_output=$(exec::silent bash -c 'echo output && false' 2>&1 || true)
71+
unit::assert_contain "$should_have_output" "output" "should have output on error"
72+
73+
DEBUG=1
74+
local output_in_debug
75+
output_in_debug=$(exec::silent bash -c 'echo output && true' 2>&1)
76+
unit::assert_contain "$output_in_debug" "output" "should have output in debug"
77+
DEBUG="$og_debug"
78+
set -eE
79+
}
80+
81+
exec_test::test_is_fn() {
82+
# shellcheck disable=SC2034
83+
local some_var=""
84+
85+
unit::assert_success exec::is_fn exec::is_fn
86+
unit::assert_failed exec::is_fn exec_test::not_exists_for_sure
87+
unit::assert_failed exec::is_fn some_var
88+
}
89+
90+
exec_test::all() {
91+
unit::test exec_test::test_output
92+
unit::test exec_test::test_is_cmd_available
93+
unit::test exec_test::test_is_fn
94+
}

0 commit comments

Comments
 (0)