Browse Source

Initial commit

Alois Mahdal 6 years ago
commit
0ffade374a

+ 4
- 0
Makefile View File

@@ -0,0 +1,4 @@
1
+# See LICENSE.md file for copyright and license details.
2
+
3
+MKIT_DIR=/usr/share/jattool/tdk/utils/mkit
4
+include $(MKIT_DIR)/mkit.mk

+ 152
- 0
README.md View File

@@ -0,0 +1,152 @@
1
+preupgrade-assistant JAT test suite
2
+===================================
3
+
4
+This is an independent test suite for preupgrade-assistant that makes use
5
+of JATS - Just A Test System.
6
+
7
+JATS defines test suite format, which is a directory tree consisting of
8
+individual tests.  These individual tests can in principle be implemented
9
+in any language, but for now *shellfu-bash-jat* is the only available
10
+library.
11
+
12
+
13
+Dependencies - test machine
14
+---------------------------
15
+
16
+All specific dependencies are available in [amahdal/jats][aj] COPR project.
17
+However, since preupgrade-assistant itself is only available for RHEL6,
18
+which does not have native COPR support, you will need to add repositories
19
+manually.
20
+
21
+  [aj]: https://copr.fedorainfracloud.org/coprs/amahdal/jats/
22
+
23
+On the testing machine, you will need:
24
+
25
+ *  shellfu-bash-jat - the main JAT library,
26
+ *  shellfu-bash-preupg - preupgrade-assistant test library,
27
+ *  jattool - harness, exploration and reporting toolkit
28
+ *  jats-preupgrade-assistant - this test suite
29
+
30
+Note that tests don't formally depend on preupgrade-assistant itself, so you will
31
+need to install it manually. (This is to help you retain full control of the
32
+preupgrade-assistant version; in future there will be mechanisms to help with that
33
+but for now manual is the safest.).
34
+
35
+Also note that you don't need to install all sub-components of jattool: jattool-tdk
36
+and jattool-report require things not available easily on all RHEL versions and are
37
+normally only useful on workstations anyway.
38
+
39
+Last but not least: you don't really need to install the jats-preupgrade-assistant;
40
+you could do away with just cloning this repo.  However, RPM will help you with
41
+the dependencies, so it's advised to install it even if you want to run from the
42
+repo.
43
+
44
+
45
+Running tests
46
+-------------
47
+
48
+At this point, most tests should work without installation.   That is, just
49
+clone this repo and run
50
+
51
+    jattool tfind
52
+
53
+to see lists of tests.   Each JAT test is a directory, so above should give
54
+you list of directories: you can then run any of them using `jattool runtest`,
55
+eg.:
56
+
57
+    jattool runtest ./src/api/binary_req
58
+
59
+
60
+Dependencies - worksation
61
+-------------------------
62
+
63
+Since your workstation is probably Fedora, you can use the modern ways:
64
+
65
+    dnf copr enable amahdal/jats
66
+    dnf install shellfu-bash-jat jattool jattool-report jattool-tdk
67
+                #\
68
+        # don't be put off of the number of dependencies; let's just say
69
+        # that author of Shellfu loves granularity :-)
70
+
71
+This will give you basic "test development kit".  More on that later.
72
+
73
+
74
+Exploring (and hacking on) tests
75
+--------------------------------
76
+
77
+I won't go into details; I'll tell you just enough to get you started,
78
+but be aware that **(mostly) everything is (mostly) documented** and
79
+primary ways to get help (actually more like reference, but helps)
80
+using *sfdoc* tool, which should be on your worksation by now.
81
+
82
+Tests normally only consist of one important file, named ... you
83
+guessed it...  *test*.  (There's also *main.fmf*, but that only contains
84
+meta-data, which is not even really used these days.)
85
+
86
+    $ tree src/api/binary_req
87
+    src/api/binary_req
88
+    ├── main.fmf
89
+    └── test
90
+
91
+So open that file:  it's a Bash script with extra "enhancements":  you'll see things
92
+like:
93
+
94
+    shellfu import jat
95
+    shellfu import preupg
96
+    shellfu import ...
97
+    shellfu import xcase
98
+
99
+Shellfu platform brings modularity to Bash, so the names above are names
100
+of modules.  `jat` is a module name.  And you can get reference on the module
101
+
102
+    sfdoc jat
103
+
104
+Since this is Bash, modules contain just functions and variables.  And since
105
+Bash has no namespaces, an important convention for (almost) all modules
106
+is in place:
107
+
108
+ *  any functions defined by module `foo` must be named by `foo__` prefix,
109
+ *  any variables defined by module `foo` must be named by `FOO__` prefix.
110
+
111
+Eg. an initializing function from module *bar* would have to be called
112
+`bar__init()`.
113
+
114
+Yep, this is a bit annoying, but:
115
+
116
+ *  you'll get used,
117
+
118
+ *  since Bash has no namespaces, this is the only way to avoid conflicts
119
+    without having to read every imported module's source code (recursively,
120
+    and after every update).
121
+
122
+ *  it can actually be helpful: seeing function like `jat__eval`, you
123
+    *immediately know* it's from *jat* module (heck, you can call `sfdoc
124
+    -O jat__eval`),
125
+
126
+ *  the above also applies to possible tools you might want to develop (it's
127
+    possible to *parse* module name from object name),
128
+
129
+ *  it provides nice excuse to keep module and function names short!
130
+
131
+
132
+Creating new tests
133
+------------------
134
+
135
+**NOTE:** At the time of this writing, the test creation kit is not finished,
136
+so if you really need new test, you can just copy another one.
137
+
138
+In order to avoid duplication of work and unnecessary frustration,
139
+take following steps:
140
+
141
+ 1. Before you start, **contact maintainer** and inform them that you
142
+    are planning to write a test.  You can do this by filing an issue
143
+    in Github repo or by contacting the maintainer directly.
144
+
145
+ 2. Read [Shellfu coding style][sfcs]; tests need to follow this.
146
+
147
+ 3. Be aware that the JATS project is in early stage (`v0.0.*`), and
148
+    some (most?) pieces of coding style and conventions are not yet
149
+    written down.  A more consistent documentation is expected to arrive
150
+    before `v0.1.0`.
151
+
152
+  [sfcs]: https://github.com/AloisMahdal/shellfu/blob/last/notes/style.md

+ 17
- 0
mkit.ini View File

@@ -0,0 +1,17 @@
1
+[INCLUDE:/usr/share/jattool/tdk/skel/mkit.ini]
2
+
3
+[project]
4
+    pkgname    = jats-preupgrade-assistant
5
+    version    = 0.0.0
6
+    maintainer = Alois Mahdal <amahdal@redhat.com>
7
+
8
+[macros]
9
+    __JATS_SUITENAME__ = preupgrade-assistant
10
+    __JATS_REQUIRES__ = shellfu-bash-preupg
11
+    __JATS_REQUIRES__ = shellfu-bash-xcase
12
+    __JATS_REQUIRES__ = libxml2
13
+
14
+[files]
15
+    jats = src preupgrade-assistant
16
+
17
+#mkit version=0.0.32

+ 1
- 0
src/.jats/domain View File

@@ -0,0 +1 @@
1
+redhat.com

+ 1
- 0
src/.jats/format View File

@@ -0,0 +1 @@
1
+0.0

+ 1
- 0
src/.jats/ns View File

@@ -0,0 +1 @@
1
+oamg

+ 1
- 0
src/.jats/sut_pname View File

@@ -0,0 +1 @@
1
+preupgrade-assistant

+ 1
- 0
src/.jats/version.skel View File

@@ -0,0 +1 @@
1
+__MKIT_PROJ_VERSION__

+ 2
- 0
src/api/binary_req/main.fmf View File

@@ -0,0 +1,2 @@
1
+description: binary_req auto-check
2
+timeout: 90m

+ 163
- 0
src/api/binary_req/test View File

@@ -0,0 +1,163 @@
1
+#!/bin/bash
2
+
3
+shellfu import jat
4
+shellfu import jat_dump
5
+shellfu import preupg
6
+shellfu import preupg_fupath
7
+shellfu import xcase
8
+
9
+T_MESSAGE=
10
+T_RISKTXT='Please, install all required packages (and binaries) and run preupg again to process check properly.'
11
+#shellcheck disable=SC2034
12
+PREUPG__RULE=xccdf_preupg_rule_api_binary_req_check
13
+
14
+assert_irisknum() {
15
+    jat__cmp -h "number of per-item risks is $1" \
16
+        "$(wc -l <irisks)" eq "$1"
17
+}
18
+
19
+mkbrq() {
20
+    #
21
+    # Produce the binary_req INI key/value pair
22
+    #
23
+    local head=true
24
+    test -n "$bins" || return 0
25
+    echo -n "binary_req = "
26
+    for bin in "${bins[@]}";
27
+    do
28
+        $head || echo -n ', '
29
+        case $bin in
30
+            mandatory)  echo -n "rpm" ;;
31
+            impossible) echo -n "nonexistentbin$(rtoken)" ;;
32
+        esac
33
+        head=false
34
+    done
35
+    echo
36
+}
37
+
38
+rtoken() {
39
+    head -c 1000 /dev/urandom \
40
+      | md5sum \
41
+      | head -c 7
42
+}
43
+
44
+XCASE__ARRAYS=bins
45
+
46
+xcase__enum() {
47
+    #
48
+    # Enumerate subtest ids
49
+    #
50
+    # Variables:
51
+    #
52
+    #  *  lang - language used: `py` for Python, `sh` for Bash
53
+    #
54
+    #  *  bins - binary "availability classes" used for testing.  This defines
55
+    #            what kind of binary name will be added to binary_req.  Multiple
56
+    #            classes mean there will be multiple binary names.
57
+    #
58
+    #            `mandatory` means a binary such as "rpm" that is impossible to
59
+    #            *not* be on the system.  `impossible` means a randomly generated
60
+    #            binary name.
61
+    #
62
+    #
63
+
64
+    for lang in py sh;
65
+    do
66
+        echo lang=$lang,bins=mandatory
67
+        echo lang=$lang,bins=impossible
68
+        echo lang=$lang,bins=
69
+        echo lang=$lang,bins=mandatory+mandatory
70
+        echo lang=$lang,bins=mandatory+impossible
71
+        echo lang=$lang,bins=impossible+mandatory
72
+        echo lang=$lang,bins=impossible+impossible
73
+    done
74
+
75
+}
76
+
77
+#shellcheck disable=SC2154
78
+xcase__setup() {
79
+    #
80
+    # Prepare for subtest
81
+    #
82
+    T_MESSAGE=message$(rtoken)
83
+    {
84
+        echo '[preupgrade]'
85
+        mkbrq
86
+        echo "[MODULE]"
87
+        echo "GROUP = api"
88
+        echo "NAME = binary_req"
89
+        echo "LANG = $lang"
90
+        case $lang in
91
+            py)
92
+                echo "CODE = log_info('$T_MESSAGE')"
93
+                echo "CODE = exit_informational()"
94
+                ;;
95
+            sh)
96
+                echo "CODE = log_info $T_MESSAGE"
97
+                echo "CODE = exit_informational"
98
+                ;;
99
+        esac
100
+    } > module.ini
101
+    preupg_fupath RHEL6_7 module.ini
102
+    jat__cmd -h "work around BZ#1368823" \
103
+        cp -ar RHEL6_7 RHEL6_7-backup
104
+    PREUPG__UPATH="RHEL6_7/all-xccdf.xml" \
105
+        preupg__run1
106
+    preupg__get_messages > messages
107
+    preupg__get_risks > risks
108
+    grep 'HIGH: Binary .* is not installed' risks > irisks
109
+}
110
+
111
+xcase__test() {
112
+    #
113
+    # Do the work
114
+    #
115
+    local o_behavior=ok     # behavior class
116
+    local o_irisknum=0      # per-item risks
117
+
118
+    for bin in "${bins[@]}"
119
+    do
120
+        case $bin in
121
+            impossible)
122
+                o_behavior=fail
123
+                ((o_irisknum++))
124
+                ;;
125
+        esac
126
+    done
127
+
128
+    case $o_behavior in
129
+        ok)
130
+            preupg__assert    \
131
+                   result "informational"   \
132
+                -N risk.high "$T_RISKTXT"   \
133
+                   msg.info "$T_MESSAGE"
134
+            assert_irisknum 0
135
+            ;;
136
+        fail)
137
+            preupg__assert    \
138
+                   result "needs_action"   \
139
+                   risk.high "$T_RISKTXT"   \
140
+                -N msg.info "$T_MESSAGE"
141
+            assert_irisknum $o_irisknum
142
+            ;;
143
+    esac
144
+
145
+}
146
+
147
+xcase__diag() {
148
+    #
149
+    # Burp up some diag
150
+    #
151
+    jat_dump__file module.ini risks messages irisks
152
+}
153
+
154
+xcase__cleanup() {
155
+    #
156
+    # Clean up after subtest
157
+    #
158
+    preupg__rmresult
159
+}
160
+
161
+
162
+xcase__run -v
163
+preupg__Cleanup

+ 2
- 0
src/api/deploy_hook/main.fmf View File

@@ -0,0 +1,2 @@
1
+description: hook deployment
2
+timeout: 90m

+ 272
- 0
src/api/deploy_hook/test View File

@@ -0,0 +1,272 @@
1
+#!/bin/bash
2
+
3
+shellfu import jat_dump
4
+shellfu import preupg
5
+shellfu import preupg_fupath
6
+shellfu import xcase
7
+
8
+PACKAGE="preupgrade-assistant"
9
+#shellcheck disable=SC2034
10
+PREUPG__RULE=xccdf_preupg_rule_api_deploy_hook_check
11
+HOOKS_ROOT="/root/preupgrade/hooks"
12
+HOOK_DIRNAME="api_deploy_hook"
13
+
14
+# mute ShellCheck
15
+Beh=
16
+CallSeq=
17
+
18
+assert_deployed() {
19
+    #
20
+    # Assert our hooks were deployed
21
+    #
22
+    local call
23
+    local arg
24
+    local hookdir
25
+    for call in "${CallSeq[@]}";
26
+    do
27
+        debug -v call
28
+        case $call in
29
+            pre.*)  hookdir="$HOOKS_ROOT/$HOOK_DIRNAME/preupgrade" ;;
30
+            post.*) hookdir="$HOOKS_ROOT/$HOOK_DIRNAME/postupgrade" ;;
31
+            #FIXME: structure unclear at the time of this writing
32
+            *)  xcase__id_error CallSeq
33
+        esac
34
+        jat__cmd -h "hook dir exists" \
35
+            test -d "$hookdir"
36
+        for arg in $(tr . '\n' <<<"${call#*.}");
37
+        do
38
+            debug -v arg
39
+            case $arg in
40
+                s*|as*)
41
+                    jat__cmd -h "hook script content is correct" \
42
+                        grep "echo hi I am script_$arg.sh" "$hookdir/run_hook"
43
+                    ;;
44
+                f*|af*)
45
+                    jat__cmd -h "auxiliary file content is correct" \
46
+                        grep "text of file_$arg" "$hookdir/file_$arg.conf"
47
+                    ;;
48
+                d*)
49
+                    jat__cmd -h "file_a from auxiliary dir is present" \
50
+                        test -s "$hookdir/dir_$arg/file_a"
51
+                    jat__cmd -h "file_b from auxiliary dir is present" \
52
+                        test -s "$hookdir/dir_$arg/file_b"
53
+                    ;;
54
+                *)
55
+                    warn "assert_deployed() arg unhandled by assert: $arg"
56
+                    ;;
57
+            esac
58
+        done
59
+    done
60
+}
61
+
62
+rtoken() {
63
+    head -c 1000 /dev/urandom \
64
+      | md5sum \
65
+      | head -c 7
66
+}
67
+
68
+mktree() {
69
+    #
70
+    # Create tree (ini for fupath) for deployment
71
+    #
72
+    local call
73
+    local arg
74
+    for call in "${CallSeq[@]}";
75
+    do
76
+        for arg in ${call//./ };
77
+        do
78
+            debug -v arg
79
+            case $arg in
80
+                post|pre|badtype|X) true                                            ;;
81
+                as*)    echo "echo hi I am script_$arg.sh; find" >"script_$arg.sh"  ;;
82
+                af*)    echo "text of file_$arg" >"file_$arg.conf"                  ;;
83
+                s*)     echo "script_$arg.sh = echo hi I am script_$arg.sh; find"   ;;
84
+                f*)     echo "file_$arg.conf = text of file_$arg"                   ;;
85
+                d*)     echo "dir_$arg/file_a = text of dir_$arg/file_a"
86
+                        echo "dir_$arg/file_b = text of dir_$arg/file_b"            ;;
87
+                *)      xcase__id_error CallSeq ;;
88
+            esac
89
+        done
90
+    done
91
+}
92
+
93
+mkcalls() {
94
+    #
95
+    # Create deploy_hook call (ini for fupath)
96
+    #
97
+    local call
98
+    local arg
99
+    for call in "${CallSeq[@]}";
100
+    do
101
+        debug -v call
102
+        echo -n "CODE = deploy_hook"
103
+        case $lang:$call in
104
+            py:pre.*)      echo -n "('preupgrade'" ;;
105
+            py:post.*)     echo -n "('postupgrade'" ;;
106
+            py:badtype.*)  echo -n "('badtype'" ;;
107
+            sh:pre.*)      echo -n " preupgrade" ;;
108
+            sh:post.*)     echo -n " postupgrade" ;;
109
+            sh:badtype.*)  echo -n " badtype" ;;
110
+            *) xcase__id_error lang CallSeq ;;
111
+        esac
112
+        for arg in $(tr . '\n' <<<"${call#*.}");
113
+        do
114
+            debug -v arg
115
+            case $lang:$arg in
116
+                py:as*)    echo -n ",'$PWD/script_$arg.sh'" ;;
117
+                py:af*)    echo -n ",'$PWD/file_$arg.conf'" ;;
118
+                py:s*)     echo -n ",'script_$arg.sh'" ;;
119
+                py:f*)     echo -n ",'file_$arg.conf'" ;;
120
+                py:d*)     echo -n ",'dir_$arg'" ;;
121
+                py:X)      echo -n ",'nonexistent_file_$(rtoken)'" ;;
122
+                sh:as*)    echo -n " $PWD/script_$arg.sh" ;;
123
+                sh:af*)    echo -n " $PWD/file_$arg.conf" ;;
124
+                sh:s*)     echo -n " script_$arg.sh" ;;
125
+                sh:f*)     echo -n " file_$arg.conf" ;;
126
+                sh:d*)     echo -n " dir_$arg" ;;
127
+                sh:X)      echo -n " nonexistent_file_$(rtoken)" ;;
128
+                *) xcase__id_error lang CallSeq ;;
129
+            esac
130
+        done
131
+        case $lang in
132
+            py) echo ')';;
133
+            sh) echo    ;;
134
+        esac
135
+    done
136
+    echo "CODE = exit_fixed$(test "$lang" = py && echo '()')"
137
+}
138
+
139
+
140
+XCASE__ARRAYS=CallSeq
141
+
142
+xcase__enum() {
143
+    #
144
+    # Enumerate subtest ids
145
+    #
146
+
147
+    # Parameters are 'Beh', behavior hint (to help simplify test phase),
148
+    # and 'CallSeq' - plus-separated list of deploy_hook() calls in this
149
+    # form:
150
+    #
151
+    #     TYPE[.ARG][.ARG]..
152
+    #
153
+    # where TYPE is either 'post' or 'pre', and ARG are symbols for the
154
+    # arguments deploy_hook() is called with:
155
+    #
156
+    #  *   sN means script N (1, 2, ...),
157
+    #  *   fN means file N (1, 2, ...),
158
+    #  *   asN and afN mean the same as sN and fN, but will be called by
159
+    #      absolute path
160
+    #  *   dN means directory N (1, 2, ...),
161
+    #  *   X means non-existent file
162
+    #
163
+    # Actual module code as well as all necessary files are created during
164
+    # setup phase.
165
+    #
166
+
167
+    {
168
+
169
+        # normal cases
170
+        #
171
+
172
+        # simplest
173
+        echo Beh=OK,CallSeq=post.s1
174
+        echo Beh=OK,CallSeq=post.s1.f1
175
+        echo Beh=OK,CallSeq=post.s1.f1.d1
176
+        echo Beh=OK,CallSeq=pre.s1
177
+        echo Beh=OK,CallSeq=pre.s1.f1
178
+        echo Beh=OK,CallSeq=pre.s1.f1.d1
179
+        echo Beh=OK,CallSeq=pre.as1
180
+        echo Beh=OK,CallSeq=pre.s1.af1
181
+
182
+        # pre and post
183
+        echo Beh=OK,CallSeq=pre.s1+post.s2
184
+        echo Beh=OK,CallSeq=pre.s1.f1.d1+post.s2.f2.d2
185
+        echo Beh=OK,CallSeq=post.s1.f1.d1+pre.s2.f2.d2
186
+
187
+        # bad cases
188
+        #
189
+
190
+        # deploy twice: same, smaller, bigger
191
+        echo Beh=BAD,CallSeq=post.s1+post.s1
192
+        echo Beh=BAD,CallSeq=post.s1.f1.d1+post.s1
193
+        echo Beh=BAD,CallSeq=post.s1+post.s1.f1.d1
194
+
195
+        # bad args: no script, script is dir, nonexistent, double arg, bad type
196
+        echo Beh=BAD,CallSeq=post.
197
+        echo Beh=BAD,CallSeq=post.d1
198
+        echo Beh=BAD,CallSeq=post.X
199
+        echo Beh=BAD,CallSeq=post.X.X
200
+        echo Beh=BAD,CallSeq=post.s1.X.X
201
+#       echo Beh=BAD,CallSeq=post.s1.f1.f1      # not sure if we can/need to catch this
202
+        echo Beh=BAD,CallSeq=post.s1.d1.X
203
+        echo Beh=BAD,CallSeq=badtype.s1
204
+
205
+    } | xcase__per lang sh py
206
+}
207
+
208
+#shellcheck disable=SC2154
209
+xcase__setup() {
210
+    #
211
+    # Prepare for subtest
212
+    #
213
+    {
214
+        echo "[MODULE]"
215
+        echo "GROUP = api"
216
+        echo "NAME = deploy_hook"
217
+        echo "LANG = $lang"
218
+        mkcalls
219
+        echo "[FILES]"
220
+        mktree
221
+    } > module.ini
222
+    preupg_fupath RHEL6_7 module.ini
223
+    PREUPG__UPATH="RHEL6_7/all-xccdf.xml" \
224
+        preupg__run1 --skip-common
225
+}
226
+
227
+xcase__test() {
228
+    #
229
+    # Do the work
230
+    #
231
+    jat__eval -S 0,1 -h "store hook file list" \
232
+        "find '$HOOKS_ROOT' -type f | grep deploy_hook > hooks"
233
+    case $Beh in
234
+
235
+        OK)
236
+            assert_deployed
237
+            jat__eval -S 1 -h "no errors were logged" \
238
+                "preupg__get_messages ERROR | grep ."
239
+            ;;
240
+
241
+        BAD)
242
+            jat__eval -S 0 -h "error was logged" \
243
+                "preupg__get_messages ERROR | grep ."
244
+            preupg__assert result 'error'
245
+            ;;
246
+
247
+        *)
248
+            xcase__id_error Beh
249
+            ;;
250
+    esac
251
+}
252
+
253
+xcase__diag() {
254
+    #
255
+    # Burp up some diag
256
+    #
257
+    jat_dump__file module.ini hooks
258
+    preupg__get_node | jat_dump__pipe NODE
259
+    preupg__get_messages | jat_dump__pipe LOG_MESSAGES
260
+}
261
+
262
+xcase__cleanup() {
263
+    #
264
+    # Clean up after subtest
265
+    #
266
+    preupg__rmresult
267
+}
268
+
269
+PREUPG__UPATH=@pass \
270
+    preupg__Run1
271
+xcase__run -v
272
+preupg__Cleanup

+ 2
- 0
src/api/logging/main.fmf View File

@@ -0,0 +1,2 @@
1
+description: logging facilities
2
+timeout: 1h

+ 106
- 0
src/api/logging/test View File

@@ -0,0 +1,106 @@
1
+#!/bin/bash
2
+
3
+shellfu import preupg
4
+shellfu import preupg_fupath
5
+shellfu import xcase
6
+shellfu import jat_dump
7
+
8
+#shellcheck disable=SC2034
9
+PREUPG__RULE=xccdf_preupg_rule_api_logging_check
10
+
11
+
12
+assert_msg_like() {
13
+    #
14
+    # Assert log message matching $1 exists
15
+    #
16
+    preupg__get_messages > msgs
17
+    jat__cmd grep "$1" msgs
18
+}
19
+
20
+xcase__enum() {
21
+    #
22
+    # Enumerate subtest ids
23
+    #
24
+    xcase__permute lang    py sh \
25
+      | xcase__per fn      log_debug log_info log_warning log_error \
26
+      | xcase__per debug   true false
27
+}
28
+
29
+#shellcheck disable=SC2154
30
+xcase__setup() {
31
+    #
32
+    # Prepare for subtest
33
+    #
34
+    local maybe_debug=""
35
+    $debug && maybe_debug="--debug"
36
+    echo "message$(head -c 1000 /dev/urandom | md5sum | head -c 7)" >t_message
37
+    {
38
+        echo "[MODULE]"
39
+        echo "GROUP = api"
40
+        echo "NAME = logging"
41
+        echo "LANG = $lang"
42
+        case $lang in
43
+            sh)
44
+                echo "CODE = $fn $(<t_message)"
45
+                echo "CODE = exit_informational"
46
+                ;;
47
+            py)
48
+                echo "CODE = $fn('$(<t_message)')"
49
+                echo "CODE = exit_informational()"
50
+                ;;
51
+        esac
52
+    } > module.mdef
53
+    preupg_fupath RHEL6_7 module.mdef
54
+    PREUPG__UPATH="RHEL6_7/all-xccdf.xml" \
55
+        preupg__run1 $maybe_debug --skip-common
56
+}
57
+
58
+xcase__test() {
59
+    #
60
+    # Do the work
61
+    #
62
+
63
+    # set oracles
64
+    #
65
+    local o_severity=""
66
+    local o_msgnum=0
67
+    local o_result=informational
68
+    local o_not=""
69
+
70
+    case $fn:$debug in
71
+        log_debug:true)   o_msgnum=1; o_severity=DEBUG    ;;
72
+        log_debug:false)  o_msgnum=0; o_severity=DEBUG    ;;
73
+        log_info:*)       o_msgnum=1; o_severity=INFO     ;;
74
+        log_warning:*)    o_msgnum=1; o_severity=WARNING  ;;
75
+        log_error:*)      o_msgnum=1; o_severity=ERROR    ;;
76
+    esac
77
+    test "$o_msgnum" -eq 0 && o_not=-N
78
+
79
+    # asserts
80
+    #
81
+    preupg__assert \
82
+        result "$o_result"  \
83
+         msgn "$o_msgnum"   \
84
+         $o_not msg.$o_severity "$(<t_message)"
85
+}
86
+
87
+xcase__diag() {
88
+    #
89
+    # Burp up some diag
90
+    #
91
+    jat_dump__file module.mdef
92
+    preupg__get_messages | jat_dump__pipe MESSAGES
93
+}
94
+
95
+xcase__cleanup() {
96
+    #
97
+    # Clean up after subtest
98
+    #
99
+    preupg__rmresult
100
+}
101
+
102
+
103
+PREUPG__UPATH=@pass \
104
+    preupg__Run1
105
+xcase__run -v
106
+preupg__Cleanup

+ 2
- 0
src/api/mseverity/main.fmf View File

@@ -0,0 +1,2 @@
1
+description: module result severity
2
+timeout: 90m

+ 310
- 0
src/api/mseverity/test View File

@@ -0,0 +1,310 @@
1
+#!/bin/bash
2
+
3
+shellfu import jat_dump
4
+shellfu import preupg
5
+shellfu import preupg_fupath
6
+shellfu import xcase
7
+
8
+#shellcheck disable=SC2034
9
+{
10
+    PREUPG__RULE="xccdf_preupg_rule_api_severity_check"
11
+    PREUPG__UPATH="RHEL6_7/all-xccdf.xml"
12
+    PREUPG__VALID_ES='0-15'
13
+    T_MSCRIPT="RHEL6_7/api/severity/check"
14
+}
15
+
16
+
17
+# ...................... #                                                     #
18
+# CASE GENERATOR HELPERS # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ #
19
+# '''''''''''''''''''''' #                                                     #
20
+
21
+dec_event() {
22
+    #
23
+    # Decode numerical event id
24
+    #
25
+    case $1 in
26
+
27
+        # the prefix is collation class decorator; gen_eseq will
28
+        # sort|uniq the result, so here you can define forced
29
+        # order.  (Due to uniq, this also means that events in same
30
+        # class will be "squashed" into one if found.)
31
+
32
+        # log messages
33
+        #
34
+        0) echo ;;
35
+        1) echo A.log_debug;;
36
+        2) echo A.log_info ;;
37
+        3) echo A.log_error ;;
38
+        4) echo A.log_warning ;;
39
+
40
+        # risks
41
+        #
42
+        10) echo ;;
43
+        11) echo A.log_slight_risk ;;
44
+        12) echo A.log_medium_risk ;;
45
+        13) echo A.log_high_risk ;;
46
+        14) echo A.log_extreme_risk ;;
47
+
48
+        # exits
49
+        #
50
+        20) echo ;;
51
+        21) echo Z.exit_pass ;;
52
+        22) echo Z.exit_fail ;;
53
+        23) echo Z.exit_error ;;
54
+        24) echo Z.exit_not_applicable ;;
55
+        25) echo Z.exit_informational ;;
56
+        26) echo Z.exit_fixed ;;
57
+    esac
58
+}
59
+
60
+echoln() {
61
+    #
62
+    # Echo each argument separately
63
+    #
64
+    for ln in "$@";
65
+    do
66
+        echo "$ln"
67
+    done
68
+}
69
+
70
+mkesg() {
71
+    #
72
+    # Make event sequence generator
73
+    #
74
+    local patt=$1
75
+    local eclass    # event class
76
+    echo -n 'echoln '
77
+    grep -o . <<<"$patt" \
78
+      | while read -r eclass;
79
+        do
80
+            case $eclass in
81
+                m)  echo -n 'm{0..4}' ;;
82
+                r)  echo -n 'm{10..14}' ;;
83
+                x)  echo -n 'x{20..28}' ;;
84
+            esac
85
+        done
86
+}
87
+
88
+gen_eseq() {
89
+    #
90
+    # Get all possible programs in pattern $1
91
+    #
92
+    # Usage: gen_eseq PATT
93
+    #
94
+    # The PATT has format C[C..], where C is a "event class" and can
95
+    # be one of following:
96
+    #
97
+    #     'm' for log message,
98
+    #     'r' for risk log,
99
+    #     'x' for exit_* call,
100
+    #
101
+    # Result is all possible unique event sequences (one per line)
102
+    # conforming to PATT, where:
103
+    #
104
+    #  *  order between 'm' and 'r' is not preserved,
105
+    #  *  'x' is always last,
106
+    #  *  each event can happen at least zero times and at most that
107
+    #     many times how many times the class was seen.
108
+    #
109
+    # Few examples to shed some light.  Programs generated by following
110
+    # PATTs may have certain properties:
111
+    #
112
+    #  *  'mrx' can have 0-1 log messages, 0-1 risks and 0-1 exits,
113
+    #  *  'mmrx' can have 0-2 log messages, 0-1 risks and 0-1 exits
114
+    #  *  'mrmx' is the same because log/risk order is not significant,
115
+    #  *  'mrxm' is still the same because 'x' is forced to be last,
116
+    #  *  'mrxx' would have 0-2 exit calls,
117
+    #
118
+    # Note that these are not real programs but just lists of events
119
+    # (named as API functions just for convenience); you will have to
120
+    # parse the list (comma-separated) and append arguments where needed.
121
+    #
122
+    local patt=$1   # event pattern
123
+    local eseq      # event id sequence
124
+    local eid       # event id
125
+    local esg       # sequence generator (makes use of '{..}' Bash syntax)
126
+    esg=$(mkesg "$patt")
127
+    eval "$esg" \
128
+      | while read -r eseq;
129
+        do
130
+            grep -oE '[[:alpha:]][[:digit:]]+' <<<"$eseq" \
131
+              | while read -0r eid;
132
+                do
133
+                    dec_event "${eid:1}"
134
+                done \
135
+              | grep . \
136
+              | sort \
137
+              | uniq \
138
+              | colrm 1 2 \
139
+              | paste -sd,
140
+        done \
141
+          | grep . \
142
+          | sort \
143
+          | uniq
144
+}
145
+
146
+
147
+# ............. #                                                              #
148
+# SETUP HELPERS # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ #
149
+# ''''''''''''' #                                                              #
150
+
151
+mkcode() {
152
+    #
153
+    # Make body of module
154
+    #
155
+    xcase__id \
156
+      | tr , '\n' \
157
+      | while read -r event;
158
+        do
159
+            case $event in
160
+                log_*_risk) echo "$event risk.by.$event" ;;
161
+                log_*)      echo "$event message.from.$event" ;;
162
+                exit_*)     echo "$event" ;;
163
+            esac
164
+        done
165
+}
166
+
167
+
168
+# ............. #                                                              #
169
+# INTROSPECTION # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ #
170
+# ''''''''''''' #                                                              #
171
+
172
+risksort() {
173
+    #
174
+    # Sort risk log calls based on severity (decorated sort)
175
+    #
176
+    local call      # the risk call
177
+    local args      # ... args (finally ignored)
178
+    while read -r call args;
179
+    do
180
+        case $call in
181
+            log_slight_risk)    echo -n '1 ' ;;
182
+            log_medium_risk)    echo -n '2 ' ;;
183
+            log_high_risk)      echo -n '3 ' ;;
184
+            log_extreme_risk)   echo -n '4 ' ;;
185
+        esac
186
+        echo "$call $args"
187
+    done \
188
+      | sort -n \
189
+      | cut -d' ' -f2
190
+}
191
+
192
+logmsort() {
193
+    #
194
+    # Sort log message calls based on severity (decorated sort)
195
+    #
196
+    local call      # the log call
197
+    local args      # ... args (finally ignored)
198
+    while read -r call args;
199
+    do
200
+        case $call in
201
+            log_debug)      echo -n '1 ' ;;
202
+            log_info)       echo -n '2 ' ;;
203
+            log_warning)    echo -n '3 ' ;;
204
+            log_error)      echo -n '4 ' ;;
205
+        esac
206
+        echo "$call $args"
207
+    done \
208
+      | sort -n \
209
+      | cut -d' ' -f2
210
+}
211
+
212
+get_worst_risk() {
213
+    grep '^log_[a-z]*_risk' "$T_MSCRIPT" \
214
+      | risksort \
215
+      | tail -1
216
+}
217
+
218
+get_first_exit() {
219
+    grep ^exit_ "$T_MSCRIPT" \
220
+      | head -1
221
+}
222
+
223
+get_risknum() {
224
+    grep -c '^log_[a-z]*_risk' "$T_MSCRIPT"
225
+}
226
+
227
+get_worst_logm() {
228
+    grep '^log_' "$T_MSCRIPT" \
229
+      | grep -v '_risk\b' \
230
+      | logmsort \
231
+      | tail -1
232
+}
233
+
234
+
235
+# .............. #                                                             #
236
+# XCASE HANDLERS # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ #
237
+# '''''''''''''' #                                                             #
238
+
239
+xcase__enum() {
240
+    gen_eseq rx
241
+    #FIXME: add larger modes such as 'rrx', 'mrx' or 'rxx'
242
+}
243
+
244
+
245
+xcase__setup() {
246
+    {
247
+        echo '[MODULE]'
248
+        echo 'GROUP = api'
249
+        echo 'NAME = severity'
250
+        mkcode | sed 's/^/CODE = /'
251
+    } > module.mdef
252
+    preupg_fupath RHEL6_7 "module.mdef"
253
+}
254
+
255
+xcase__test() {
256
+    local o_es          # oracle: exit status
257
+    local o_result      # oracle: assessment result
258
+
259
+    # set up oracles
260
+    #
261
+    case $(get_first_exit):$(get_worst_risk) in
262
+        # obviously error
263
+        #
264
+        :*)                         o_es=2; o_result=error ;;
265
+        exit_error:*)               o_es=2; o_result=error ;;
266
+
267
+        # valid calls to exit_fail
268
+        #
269
+        exit_fail:log_slight_risk)  o_es=0; o_result=needs_inspection ;;
270
+        exit_fail:log_medium_risk)  o_es=0; o_result=needs_inspection ;;
271
+        exit_fail:log_high_risk)    o_es=1; o_result=needs_action ;;
272
+        exit_fail:log_extreme_risk) o_es=2; o_result=fail ;;
273
+
274
+        # (mostly in)valid calls to other exit_*
275
+        #
276
+        exit_pass:*)                o_es=0; o_result=pass ;;
277
+        exit_not_applicable:*)      o_es=0; o_result=notapplicable ;;
278
+        exit_informational:*)       o_es=0; o_result=informational ;;
279
+        exit_fixed:*)               o_es=0; o_result=fixed ;;
280
+        exit_fail:)                 o_es=2; o_result=fail ;;
281
+
282
+    esac
283
+
284
+    # run preupg
285
+    #
286
+    PREUPG__VALID_ES=$o_es \
287
+        preupg__run1 --skip-common
288
+    preupg__assert result "$o_result"
289
+}
290
+
291
+xcase__diag() {
292
+    jat_dump__file module.mdef "$T_MSCRIPT"
293
+    preupg__get_risks | jat_dump__pipe RESULT_RISKS
294
+    preupg__get_node | jat_dump__pipe RESULT_NODE
295
+}
296
+
297
+xcase__cleanup() {
298
+    jat__cmd rm -rf RHEL6_7
299
+    preupg__rmresult
300
+}
301
+
302
+
303
+# ............ #                                                               #
304
+# MAIN() STUFF # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ #
305
+# '''''''''''' #                                                               #
306
+
307
+PREUPG__UPATH=@pass \
308
+    preupg__Run1
309
+xcase__run
310
+preupg__Cleanup

+ 2
- 0
src/api/nativity/main.fmf View File

@@ -0,0 +1,2 @@
1
+description: package "nativity" functions
2
+timeout: 3h

+ 263
- 0
src/api/nativity/test View File

@@ -0,0 +1,263 @@
1
+#!/bin/bash
2
+# vim: dict+=/usr/share/beakerlib/dictionary.vim cpt=.,w,b,u,t,i,k
3
+# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
4
+#
5
+#   runtest.sh of /CoreOS/preupgrade-assistant/api/nativity
6
+#   Description: package "nativity" functions
7
+#   Author: Alois Mahdal <amahdal@redhat.com>
8
+#
9
+# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
10
+#
11
+#   Copyright (c) 2016 Red Hat, Inc.
12
+#
13
+#   This program is free software: you can redistribute it and/or
14
+#   modify it under the terms of the GNU General Public License as
15
+#   published by the Free Software Foundation, either version 2 of
16
+#   the License, or (at your option) any later version.
17
+#
18
+#   This program is distributed in the hope that it will be
19
+#   useful, but WITHOUT ANY WARRANTY; without even the implied
20
+#   warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
21
+#   PURPOSE.  See the GNU General Public License for more details.
22
+#
23
+#   You should have received a copy of the GNU General Public License
24
+#   along with this program. If not, see http://www.gnu.org/licenses/.
25
+#
26
+# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
27
+
28
+shellfu import jat_dump
29
+shellfu import preupg
30
+shellfu import preupg_fupath
31
+shellfu import xcase
32
+
33
+#shellcheck disable=SC2034
34
+{
35
+    PREUPG__RULE=xccdf_preupg_rule_api_nativity_check
36
+    JAT_DUMP__LIMIT_L=2000
37
+    JAT_DUMP__LIMIT_B=20000
38
+    Fn=
39
+    Dno=
40
+    Check=
41
+    Lang=
42
+}
43
+
44
+EXCLUDED=git
45
+FOREIGN=preupgrade-assistant-CoreOS-preupgrade-assistant-Library-dummyreq
46
+NATIVE=rpm
47
+NINST=habakukova_asymetricka-skladanka
48
+
49
+assert_foreign() {
50
+    #
51
+    # Assert that package $1 was not deemed native
52
+    #
53
+    local pkg=$1
54
+    case $Fn in
55
+        get_dist_native_list)
56
+            rlRun "grep '$pkg' r_native" \
57
+                1 "package $pkg not considered native"
58
+            ;;
59
+        is_dist_native)
60
+            rlAssertNotEquals \
61
+                "package $pkg not considered native" \
62
+                "$(cat r_es)" 0
63
+            ;;
64
+    esac
65
+}
66
+
67
+assert_native() {
68
+    #
69
+    # Assert that package $1 was deemed native
70
+    #
71
+    local pkg=$1
72
+    case $Fn in
73
+        get_dist_native_list)
74
+            rlRun "grep '$pkg' r_native" \
75
+                0 "package $pkg considered native"
76
+            ;;
77
+        is_dist_native)
78
+            rlAssertEquals \
79
+                "package $pkg considered native" \
80
+                "$(cat r_es)" 0
81
+            ;;
82
+    esac
83
+}
84
+
85
+xcase__enum() {
86
+    #
87
+    # Enumerate subtest ids
88
+    #
89
+    # Format:
90
+    #
91
+    #     Fn=FN,Dno=DNO,Check=CHECK
92
+    #
93
+    # FN is name of relevant function that is tested.
94
+    #
95
+    # DNO stands for 'dist_native override', and governs value
96
+    # passed to preupg__run1() to override
97
+    # 'native' mechanism,  In this case, it can be:
98
+    #
99
+    #  *  'all', 'sign' or empty - pass directly
100
+    #
101
+    #  *  'excluded' pass special value to exclude one single package
102
+    #     from nativity
103
+    #
104
+    # CHECK can be (some make sense only for certain functions):
105
+    #
106
+    #  *  'foreign' - query for surely non-native package
107
+    #
108
+    #  *  'ninst' - query for package that's not installed
109
+    #
110
+    #  *  'native' - query for "surely" native package (this can be hard to
111
+    #     maintain when distribution this test is runnning is under
112
+    #     development)
113
+    #
114
+    #  *  'excluded' - query for package excluded from native by DNO
115
+    #
116
+    #  *  'diff' - use standard diff tool to compare expected result to
117
+    #     actual result
118
+    #
119
+    {
120
+        echo Fn=is_dist_native,Dno=,Check=foreign
121
+        echo Fn=is_dist_native,Dno=,Check=native
122
+        echo Fn=is_dist_native,Dno=,Check=ninst
123
+        echo Fn=get_dist_native_list,Dno=,Check=foreign
124
+        echo Fn=get_dist_native_list,Dno=,Check=native
125
+        echo Fn=get_dist_native_list,Dno=all,Check=diff
126
+        echo Fn=get_dist_native_list,Dno=excluded,Check=diff
127
+        echo Fn=get_dist_native_list,Dno=excluded,Check=excluded
128
+#       echo Fn=get_dist_native_list,Dno=sign,Check=diff   #FIXME find out how to get oracle
129
+#       echo Fn=get_dist_native_list,Dno=,Check=diff       #FIXME find out how to get oracle
130
+    } | xcase__per Lang py sh
131
+}
132
+
133
+xcase__setup() {
134
+    #
135
+    # Prepare for subtest
136
+    #
137
+    # Dropped files:
138
+    #
139
+    #  *  r_native -- result: native package name list from get_dist_native_list()
140
+    #  *  r_es     -- result: exit status after calling is_dist_native()
141
+    #
142
+    local t_dno     # dist_native override
143
+
144
+    # Create module
145
+    #
146
+    {
147
+        echo "[MODULE]"
148
+        echo "GROUP = api"
149
+        echo "NAME = nativity"
150
+        echo "LANG = $Lang"
151
+        #shellcheck disable=SC2028
152
+        case $Lang in
153
+            sh)
154
+                case $Fn:$Check in
155
+                    is_dist_native:foreign) echo "CODE = is_dist_native '$FOREIGN'; echo \$? > '$PWD/r_es'" ;;
156
+                    is_dist_native:native)  echo "CODE = is_dist_native '$NATIVE';  echo \$? > '$PWD/r_es'" ;;
157
+                    is_dist_native:ninst)   echo "CODE = is_dist_native '$NINST';   echo \$? > '$PWD/r_es'" ;;
158
+                    get_dist_native_list:*) echo "CODE = get_dist_native_list | LC_ALL=C sort > '$PWD/r_native'" ;;
159
+                esac
160
+                echo "CODE = exit_pass"
161
+                ;;
162
+            py)
163
+                echo "CODE = def keep_native(lst):"
164
+                echo "CODE =     with open('$PWD/r_native', 'w') as fh:"
165
+                echo "CODE =         fh.write('\\n'.join(sorted(lst)) + '\\n')"
166
+                echo "CODE = "
167
+                echo "CODE = def keep_es(bit):"
168
+                echo "CODE =     with open('$PWD/r_es', 'w') as fh:"
169
+                echo "CODE =         fh.write('0\\n' if bit else '1\\n')"
170
+                echo "CODE = "
171
+                case $Fn:$Check in
172
+                    is_dist_native:foreign) echo "CODE = keep_es(is_dist_native('$FOREIGN'))" ;;
173
+                    is_dist_native:native)  echo "CODE = keep_es(is_dist_native('$NATIVE'))"  ;;
174
+                    is_dist_native:ninst)   echo "CODE = keep_es(is_dist_native('$NINST'))"   ;;
175
+                    get_dist_native_list:*) echo "CODE = keep_native(get_dist_native_list())" ;;
176
+                esac
177
+                echo "CODE = exit_pass()"
178
+                ;;
179
+        esac
180
+    } > module.ini
181
+    preupg_fupath RHEL6_7 module.ini
182
+
183
+    # prepare dist_native override
184
+    #
185
+    case $Dno in
186
+        all)        t_dno="all"         ;;
187
+        excluded)   t_dno="-$EXCLUDED"  ;;
188
+        sign)       t_dno="sign"        ;;
189
+        "")         t_dno=""            ;;
190
+    esac
191
+
192
+    # ensure package (non-)presence)
193
+    #
194
+    case $Check in
195
+        foreign)    rlAssertRpm "$FOREIGN"  ;;
196
+        native)     rlAssertRpm "$NATIVE"   ;;
197
+        ninst)      rlAssertNotRpm "$NINST" ;;
198
+    esac
199
+
200
+    # collect data
201
+    #
202
+    PREUPG__DISTNATIVE="$t_dno" \
203
+    PREUPG__UPATH="RHEL6_7/all-xccdf.xml" \
204
+        preupg__run1
205
+}
206
+
207
+xcase__test() {
208
+    #
209
+    # Do the work
210
+    #
211
+    # Dropped files:
212
+    #
213
+    #  *  rpm_qa   -- all installed package names
214
+    #  *  o_native -- oracle: all native package names
215
+    #  *  r_diff   -- result: diff of above two (dumped as error)
216
+    #
217
+
218
+    # prepare oracles
219
+    #
220
+    rpm -qa --qf='%{NAME}\n' | LC_ALL=C sort > rpm_qa
221
+    case $Dno:$Check in
222
+        all:diff)       cp rpm_qa o_native              ;;
223
+        excluded:diff)  <rpm_qa grep -vxF "$EXCLUDED" > o_native  ;;
224
+        sign:diff)      echo 42 >o_native               ;; #FIXME: who knows?
225
+        :diff)          echo 42 >o_native               ;; #FIXME: who knows?
226
+    esac
227
+
228
+    # do the test
229
+    #
230
+    case $Check in
231
+        diff)       rlRun "diff -U 1 o_native r_native > r_diff" \
232
+                        0 "native list is same as expected" \
233
+                     || jat_dump__file -E r_diff ;;
234
+        native)     assert_native  "$NATIVE"     ;;
235
+        excluded)   assert_foreign "$EXCLUDED"   ;;
236
+        foreign)    assert_foreign "$FOREIGN"    ;;
237
+        ninst)      assert_foreign "$NINST"      ;;
238
+    esac
239
+}
240
+
241
+xcase__diag() {
242
+    #
243
+    # Burp up some diag
244
+    #
245
+    jat_dump__file module.ini
246
+    preupg__get_messages | jat_dump__pipe MESSAGE
247
+}
248
+
249
+xcase__cleanup() {
250
+    #
251
+    # Clean up after subtest
252
+    #
253
+    preupg__rmresult
254
+}
255
+
256
+
257
+jat__log_info "EXCLUDED='$EXCLUDED'"
258
+jat__log_info "FOREIGN='$FOREIGN'"
259
+jat__log_info "NATIVE='$NATIVE'"
260
+jat__log_info "NINST='$NINST'"
261
+
262
+xcase__run -v
263
+preupg__Cleanup

+ 3
- 0
src/preupg/devel_mode/main.fmf View File

@@ -0,0 +1,3 @@
1
+description: devel mode
2
+timeout: 30m
3
+reference: https://bugzilla.redhat.com/show_bug.cgi?id=1231410

+ 63
- 0
src/preupg/devel_mode/test View File

@@ -0,0 +1,63 @@
1
+#!/bin/bash
2
+
3
+shellfu import jat_dump
4
+shellfu import preupg
5
+shellfu import preupg_fupath
6
+shellfu import xcase
7
+
8
+PREUPG__RULE=xccdf_preupg_rule_output_set_check
9
+PREUPG__DISTNATIVE=""
10
+
11
+assert_devel_mode_on() {
12
+    jat__cmd -h "devel mode is on" \
13
+        grep 'DEVEL_MODE=1' set.out
14
+}
15
+
16
+assert_devel_mode_not_on() {
17
+    jat__cmd -h "devel mode is not on" -S 1 \
18
+        grep 'DEVEL_MODE=1' set.out
19
+}
20
+
21
+
22
+xcase__enum() {
23
+    echo on
24
+    echo off
25
+}
26
+
27
+xcase__setup() {
28
+    jat__cmd mkdir -p /var/cache/preupgrade
29
+    case $(xcase__id) in
30
+        on)     jat__cmd touch /var/cache/preupgrade/devel_mode  ;;
31
+        off)    jat__cmd rm -f /var/cache/preupgrade/devel_mode  ;;
32
+    esac
33
+    {
34
+        echo '[MODULE]'
35
+        echo "GROUP = output"
36
+        echo "NAME = set"
37
+        echo "CODE = set > '$PWD/set.out'"
38
+        echo "CODE = exit_pass"
39
+    } > module.ini
40
+    preupg_fupath RHEL6_7 module.ini
41
+    PREUPG__UPATH="RHEL6_7/all-xccdf.xml" \
42
+        preupg__run1
43
+}
44
+
45
+xcase__test() {
46
+    case $(xcase__id) in
47
+        on)     assert_devel_mode_on     ;;
48
+        off)    assert_devel_mode_not_on ;;
49
+    esac
50
+}
51
+
52
+xcase__diag() {
53
+    preupg__get_node | jat_dump__pipe NODE
54
+    jat_dump__file -l 1000 -b 20000 set.out
55
+}
56
+
57
+xcase__cleanup() {
58
+    jat__cmd rm -rf /var/cache/preupgrade
59
+    preupg__rmresult
60
+}
61
+
62
+xcase__run
63
+preupg__Cleanup

+ 2
- 0
src/preupg/list-rules/main.fmf View File

@@ -0,0 +1,2 @@
1
+description: --list-rules argument
2
+timeout: 90m

+ 120
- 0
src/preupg/list-rules/test View File

@@ -0,0 +1,120 @@
1
+#!/bin/bash
2
+#shellcheck disable=SC1091,SC2034
3
+
4
+Installed=
5
+Custom=
6
+Select=
7
+
8
+shellfu import jat_dump
9
+shellfu import preupg
10
+shellfu import preupg_fupath
11
+shellfu import xcase
12
+
13
+xcase__enum() {
14
+    #
15
+    # Enumerate use case ids
16
+    #
17
+    xcase__permute Installed 0 1 2 \
18
+      | xcase__per Custom 0 1 2 \
19
+      | xcase__per Select none s_ok c_ok s_bad c_bad both
20
+}
21
+
22
+mk_cupath() {
23
+    #
24
+    # Build custom upath
25
+    #
26
+    local name
27
+    for name in "$@"; do
28
+        preupg_fupath "$name" @pass @informational @fixed
29
+    done
30
+}
31
+
32
+xcase__setup() {
33
+    #
34
+    # Setup and collect data
35
+    #
36
+    local t_selargs      # selection arguments
37
+
38
+    case $Installed in
39
+        0)  :   ;;
40
+        1)  mk_cupath INS1;     cp -r INS1 /usr/share/preupgrade ;;
41
+        2)  mk_cupath INS{1,2}; cp -r INS{1,2} /usr/share/preupgrade ;;
42
+        *)  xcase__id_error Installed ;;
43
+    esac
44
+
45
+    case $Custom in
46
+        0)  :   ;;
47
+        1)  mk_cupath CUS1     ;;
48
+        2)  mk_cupath CUS{1,2} ;;
49
+        *)  xcase__id_error Custom ;;
50
+    esac
51
+
52
+    case $Select in
53
+        none)   t_selargs=() ;;
54
+        s_ok)   t_selargs=(-s INS1) ;;
55
+        s_bad)  t_selargs=(-s BLAH) ;;
56
+        c_ok)   t_selargs=(-c CUS1/all-xccdf.xml) ;;
57
+        c_bad)  t_selargs=(-c CUS3/all-xccdf.xml) ;;
58
+        both)   t_selargs=(-s INS1 -c CUS1/all-xccdf.xml) ;;
59
+        *) xcase__id_error Select ;;
60
+    esac
61
+
62
+    jat__cmd -S 0,1,20,22 -o preupg.out -e preupg.err \
63
+        preupg --list-rules "${t_selargs[@]}"
64
+        echo $? >r_es
65
+}
66
+
67
+xcase__test() {
68
+    #
69
+    # Verify result = oracle
70
+    #
71
+    local o_err=false       # oracle: error output?
72
+    local o_es              # oracle: preupg exit status
73
+    local o_lines           # oracle: normal output line count
74
+    local r_err=false       # result: error output?
75
+    local r_es              # result: preupg exit status
76
+    local r_lines           # result: normal output line count
77
+    grep '^xccdf' preupg.out >preupg.out.filtered;  # FIXME: remove and use normal .out
78
+    r_lines=$(<preupg.out.filtered wc -l)           # after https://github.com/upgrades-migrations/preupgrade-assistant/issues/333
79
+    test -s preupg.err && r_err=true
80
+    r_es=$(<r_es)
81
+
82
+    case $Installed:$Custom:$Select in
83
+
84
+        *:both)     o_lines=0;  o_es=22; o_err=true  ;;
85
+
86
+        0:0:*)      o_lines=0;  o_es=20; o_err=true  ;;
87
+        1:*:none)   o_lines=3;  o_es=0;  o_err=false ;;
88
+        *:none)     o_lines=0;  o_es=20; o_err=true  ;;
89
+
90
+        0:*:s_ok)   o_lines=0;  o_es=20; o_err=true  ;;
91
+        *:s_ok)     o_lines=3;  o_es=0;  o_err=false ;;
92
+        *:s_bad)    o_lines=0;  o_es=20; o_err=true  ;;
93
+
94
+        *:0:c_ok)   o_lines=0;  o_es=20; o_err=true  ;;
95
+        *:c_ok)     o_lines=3;  o_es=0;  o_err=false ;;
96
+        *:c_bad)    o_lines=0;  o_es=20; o_err=true  ;;
97
+
98
+        *)  xcase__id_error Installed Custom Select ;;
99
+    esac
100
+
101
+    jat__cmp -h "number of listed lines is correct" \
102
+        "$r_lines" eq "$o_lines"
103
+    jat__cmp -h "exit status from preupg is correct" \
104
+        "$r_es" eq "$o_es"
105
+#   jat__cmp -h "error output does (not) exist as expected" \
106
+#       "$r_err" eq "$o_err"
107
+    # FIXME: enable stderr assert after https://github.com/upgrades-migrations/preupgrade-assistant/issues/333
108
+}
109
+
110
+xcase__diag() {
111
+    dump__file preupg.out preupg.out.filtered preupg.err
112
+}
113
+
114
+xcase__cleanup() {
115
+    jat__cmd rm -rf /usr/share/preupgrade/INS*
116
+    preupg__rmresult
117
+}
118
+
119
+xcase__run -v
120
+preupg__Cleanup

+ 2
- 0
src/preupg/result-files/main.fmf View File

@@ -0,0 +1,2 @@
1
+description: result*.html and similar files
2
+timeout: 30m

+ 163
- 0
src/preupg/result-files/test View File

@@ -0,0 +1,163 @@
1
+#!/bin/bash
2
+
3
+shellfu import jat_dump
4
+shellfu import preupg
5
+shellfu import preupg_fupath
6
+
7
+assert_html_ok() {
8
+    #
9
+    # Do sanity test for result.html
10
+    #
11
+    local fpath="$1"
12
+    jat__cmd -h "it's not empty: $fpath" \
13
+        test -s "$fpath"
14
+    jat__cmd -h "no _SOLUTION_MSG* placeholders: $fpath" \
15
+        -S 1 \
16
+        grep _SOLUTION_MSG "$fpath"
17
+}
18
+
19
+assert_xml_ok() {
20
+    #
21
+    # Do sanity test for result.html
22
+    #
23
+    local fpath="$1"
24
+    jat__cmd -h "its not empty: $fpath" \
25
+        test -s "$fpath"
26
+    jat__cmd -h "it's a valid XML: $fpath" \
27
+        xmllint "$fpath"
28
+}
29
+
30
+assert_tarball_ok() {
31
+    #
32
+    # Do sanity test for tarball
33
+    #
34
+    local fpath="$1"    # path to tarball
35
+    local fname         # tarball filename
36
+    local path          # one of mandatory paths from enum_tarball_paths()
37
+    local pfx           # volatile path prefix (also part of tarball name)
38
+    fname=$(basename "$fpath")
39
+    pfx=${fname%.tar.gz}
40
+    jat__cmd -h "file name determined" \
41
+        test -n "$fpath"                    || return 1
42
+    jat__cmd -h "file is not empty" \
43
+        test -s "$fpath"                    || return 1
44
+    preupg__tar_list > tarball_contents.txt
45
+    jat__cmd -h "file contents are not empty" \
46
+        test -s tarball_contents.txt        || return 1
47
+    jat__cmd -h "file layout is nested" -S 1 \
48
+        grep -v "^$pfx/" tarball_contents.txt
49
+    jat__cmd -h "shadow and gshadow files are not packed" -S 1 \
50
+        grep -we 'shadow$' -e 'gshadow$' tarball_contents.txt
51
+    for path in $(enum_tarball_paths);
52
+    do
53
+        jat__cmd -h "file $path is present" \
54
+            grep -qxF "$pfx/$path" tarball_contents.txt
55
+    done
56
+    for path in $(enum_tarball_nopaths);
57
+    do
58
+        jat__cmd -h "file $path is not present" -S 1 \
59
+            grep -qxF "$pfx/$path" tarball_contents.txt
60
+    done
61
+    jat_dump__file tarball_contents.txt
62
+}
63
+
64
+enum_tarball_paths() {
65
+    #
66
+    # Enumerate relative paths that must exist in tarball
67
+    #
68
+    # Paths here are listed *without* the "preupg_results-160608163404"
69
+    # prefix as that is volatile but expected.
70
+    #
71
+    echo README
72
+    echo cleanconf/
73
+    echo common/
74
+    echo dirtyconf/
75
+    echo kickstart/
76
+    echo noauto_postupgrade.d/
77
+    echo postupgrade.d/
78
+    echo preupgrade-scripts/
79
+    echo result.html
80
+    echo result.xml
81
+}
82
+
83
+enum_tarball_nopaths() {
84
+    #
85
+    # Enumerate relative paths that must NOT exist in tarball
86
+    #
87
+    # Paths here are listed *without* the "preupg_results-160608163404"
88
+    # prefix as that is volatile but expected.
89
+    #
90
+    echo result-admin.html  # BZ#1414322
91
+    echo result-admin.xml   # BZ#1414322
92
+}
93
+
94
+add_3pmod() {
95
+    #
96
+    # Add 3rdparty module
97
+    #
98
+    # 3rdparty modules need to be added *after* composing, so in order
99
+    # to take advantage of preupgrade-assistant/fupath, we'll build
100
+    # separate throw-away set and just move the source files.
101
+    #
102
+    preupg_fupath \
103
+        THIRD \
104
+        @3rdparty
105
+    mkdir -p FOO/3rdparty/a_custom_module
106
+    {
107
+        echo '[preupgrade]'
108
+        echo 'group_title = A nice group title'
109
+    } >FOO/3rdparty/group.ini
110
+    mv THIRD/3rdparty/a_custom_module/{solution.txt,check,module.ini} \
111
+        FOO/3rdparty/a_custom_module
112
+}
113
+
114
+jat__pstarts "prepare fake upgrade path"
115
+    preupg_fupath \
116
+        FOO \
117
+        @failed \
118
+        @fixed \
119
+        @informational \
120
+        @needs_action \
121
+        @needs_inspection \
122
+        @not_applicable \
123
+        @pass
124
+    add_3pmod
125
+    jat__cmd -h "make backup of upgrade path" \
126
+        cp -ar FOO FOO-backup
127
+jat__pend
128
+
129
+jat__pstarts "prepare results"
130
+    PREUPG__UPATH="FOO/all-xccdf.xml" \
131
+        preupg__run1
132
+    jat__cmd -h "tarball found" \
133
+        test -n "$(preupg__get_latest_tar)"
134
+    preupg__lsrules_ast \
135
+      | jat_dump__pipe AST_RULES
136
+jat__pend
137
+
138
+jat__pstartt "check if upgrade path has been changed - BZ#1368823"
139
+    jat__cmd -h "custom upgrade path has not been changed (bz1368823)" \
140
+        -o updiff \
141
+        diff -ru FOO FOO-backup
142
+    jat_dump__file -E updiff
143
+    test -s updiff && jat__submit updiff FOO.diff
144
+jat__pend
145
+
146
+jat__pstartt "check result*.html"
147
+    assert_html_ok /root/preupgrade/result.html
148
+jat__pend
149
+
150
+jat__pstartt "check result*.xml"
151
+    assert_xml_ok /root/preupgrade/result.xml
152
+jat__pend
153
+
154
+jat__pstartt "check tarball"
155
+    assert_tarball_ok "$(preupg__get_latest_tar)"
156
+jat__pend
157
+
158
+jat__pstartt "check that 3rdparty module has run"
159
+    preupg__assert -r xccdf_preupg_rule_3rdparty_a_custom_module_check \
160
+        result pass
161
+jat__pend
162
+
163
+preupg__Cleanup

+ 2
- 0
src/preupg/riskcheck/main.fmf View File

@@ -0,0 +1,2 @@
1
+description: riskcheck mode
2
+timeout: 120m

+ 86
- 0
src/preupg/riskcheck/test View File

@@ -0,0 +1,86 @@
1
+#!/bin/bash
2
+# shellcheck disable=SC2154
3
+
4
+shellfu import jat
5
+shellfu import jat_dump
6
+shellfu import preupg
7
+shellfu import xcase
8
+
9
+xcase__enum() {
10
+
11
+    echo mresult=error,verbose=on
12
+    echo mresult=failed,verbose=on
13
+    echo mresult=fixed,verbose=on
14
+    echo mresult=informational,verbose=on
15
+    echo mresult=needs_action,verbose=on
16
+    echo mresult=needs_inspection,verbose=on
17
+    echo mresult=not_applicable,verbose=on
18
+    echo mresult=pass,verbose=on
19
+
20
+    echo mresult=error,verbose=off
21
+    echo mresult=failed,verbose=off
22
+    echo mresult=fixed,verbose=off
23
+    echo mresult=informational,verbose=off
24
+    echo mresult=needs_action,verbose=off
25
+    echo mresult=needs_inspection,verbose=off
26
+    echo mresult=not_applicable,verbose=off
27
+    echo mresult=pass,verbose=off
28
+}
29
+
30
+
31
+xcase__setup() {
32
+    PREUPG__UPATH="@$mresult" \
33
+        preupg__run1 --skip-common; echo $?>o_paes
34
+}
35
+
36
+
37
+xcase__test() {
38
+    local t_vrbarg=''   # test: verbose argument
39
+    local o_es=0        # oracle: exit status
40
+    local o_out=false   # oracle: any stdout?
41
+    local o_err=false   # oracle: any stderr?
42
+    local r_es=0        # result: exit status
43
+    local o_paes        # oracle: preupg exit status
44
+    o_paes=$(<o_paes)
45
+
46
+    case $mresult:$verbose in
47
+        failed:on)   o_out=true; t_vrbarg="--verbose" ;;
48
+    esac
49
+    case $mresult in
50
+        error)            o_es=2 ;;
51
+        failed)           o_es=2 ;;
52
+        fixed)            o_es=0 ;;
53
+        informational)    o_es=0 ;;
54
+        needs_action)     o_es=1 ;;
55
+        needs_inspection) o_es=0 ;;
56
+        not_applicable)   o_es=0 ;;
57
+        pass)             o_es=0 ;;
58
+    esac
59
+
60
+    jat__cmd -o preupg.out -e preupg.err -S $o_es \
61
+        preupg --riskcheck $t_vrbarg; r_es=$?
62
+    preupg__LibraryLimited loscap "HTML generation warning removed" \
63
+     && jat__eval "sed -i '/Generating simply styled report due to the limitations of the installed OpenSCAP/d' preupg.out"
64
+    #FIXME: the message should be in stderr after https://github.com/upgrades-migrations/preupgrade-assistant/issues/315
65
+    jat__cmp -h "exit status corresponds to module result" \
66
+        "$r_es" eq "$o_es"
67
+    jat__cmp -h "exit status is the same as of preupg" \
68
+        "$r_es" eq "$o_paes"
69
+    $o_out && jat__cmd -S 0 -h "there is some stdout" test -s preupg.out
70
+    $o_out || jat__cmd -S 1 -h "there is no stdout"   test -s preupg.out
71
+    $o_err && jat__cmd -S 0 -h "there is some stderr" test -s preupg.err
72
+    $o_err || jat__cmd -S 1 -h "there is no stderr"   test -s preupg.err
73
+}
74
+
75
+xcase__diag() {
76
+    jat_dump__file preupg.out preupg.err
77
+}
78
+
79
+xcase__cleanup() {
80
+    preupg__rmresult
81
+}
82
+
83
+PREUPG__UPATH=@pass \
84
+    preupg__Run1
85
+xcase__run -v
86
+preupg__Cleanup

+ 2
- 0
src/preupg/select-rules/main.fmf View File

@@ -0,0 +1,2 @@
1
+description: --select-rules argument
2
+timeout: 1h

+ 67
- 0
src/preupg/select-rules/test View File

@@ -0,0 +1,67 @@
1
+#!/bin/bash
2
+
3
+shellfu import jat
4
+shellfu import jat_dump
5
+shellfu import preupg
6
+shellfu import preupg_fupath
7
+shellfu import xcase
8
+
9
+xcase__enum() {
10
+    #
11
+    # Enumerate use case ids
12
+    #
13
+    echo one
14
+    echo two
15
+    echo all
16
+}
17
+
18
+xcase__setup() {
19
+    #
20
+    # Setup and collect data
21
+    #
22
+    local regex
23
+    case $(xcase__id) in
24
+        one)    regex="pass"    ;;
25
+        two)    regex="needs_"  ;;
26
+        all)    regex="."       ;;
27
+        *)      xcase__id_error ;;
28
+    esac
29
+    preupg_fupath \
30
+        RHEL6_7 \
31
+        @pass \
32
+        @informational \
33
+        @fixed \
34
+        @needs_action \
35
+        @needs_inspection
36
+    PREUPG__UPATH="$PWD/RHEL6_7/all-xccdf.xml" \
37
+    PREUPG__RULE_REGEX="$regex" \
38
+        preupg__run1
39
+}
40
+
41
+xcase__test() {
42
+    #
43
+    # Setup and collect data
44
+    #
45
+    local r_rnum    # result: rule number
46
+    local o_rnum    # oracle: rule number
47
+    r_rnum=$(preupg__lsrules_ast | wc -l)
48
+    case $(xcase__id) in
49
+        one)    o_rnum=1  ;;
50
+        two)    o_rnum=2  ;;
51
+        all)    o_rnum=5  ;;
52
+        *)      xcase__id_error ;;
53
+    esac
54
+    jat__cmp -h "number of ran rules is as expected" \
55
+        "$r_rnum" eq "$o_rnum"
56
+}
57
+
58
+xcase__diag() {
59
+    preupg__lsrules_ast | jat_dump__pipe LSRULES_AST
60
+}
61
+
62
+xcase__cleanup() {
63
+    preupg__rmresult
64
+}
65
+
66
+xcase__run -c /root
67
+preupg__Cleanup

+ 2
- 0
src/tools/mset-new/main.fmf View File

@@ -0,0 +1,2 @@
1
+description: Create new module set
2
+timeout: 1h

+ 54
- 0
src/tools/mset-new/test View File

@@ -0,0 +1,54 @@
1
+#!/bin/bash
2
+
3
+shellfu import jat_dump
4
+
5
+reply_md() {
6
+    local case=$1
7
+    case $case in
8
+        new)
9
+            echo FOO
10
+            echo 6
11
+            echo 7
12
+            echo hello
13
+            echo joe
14
+            echo sh
15
+            echo just a test module
16
+            echo something something
17
+            ;;
18
+        add)
19
+            echo FOO
20
+            echo y
21
+            echo hello
22
+            echo jane
23
+            echo sh
24
+            echo just another test module
25
+            echo something something else else
26
+            ;;
27
+    esac
28
+}
29
+
30
+jat__pstartt "create module set"
31
+    jat__eval "reply_md new | preupg-content-creator"
32
+    jat__eval "reply_md add | preupg-content-creator"
33
+    jat__eval "echo log_info Hello >> FOO/hello/joe/check"
34
+    jat__eval "echo exit_pass >> FOO/hello/joe/check"
35
+    jat__eval "echo log_info Bye >> FOO/hello/jane/check"
36
+    jat__eval "echo exit_pass >> FOO/hello/jane/check"
37
+    jat__eval "preupg-xccdf-compose FOO 1>pxc.out 2>pxc.err"
38
+    jat__eval "mv FOO FOO-raw; mv FOO-results FOO"
39
+jat__pend
40
+
41
+jat__pstartt "check for specific problems"
42
+    jat__eval -S 1 -h "solution key was not added (PR#328)" -b pa_pr_328 \
43
+        "find FOO -name module.ini | xargs -L1 grep -w ^solution | grep ."
44
+    jat__eval -S 1 -h "no warning about solution key (PR#328)" -b pa_pr_328 \
45
+        "grep -q 'Warning: tags: .solution. are not allowed in config file' pxc.err"
46
+jat__pend
47
+
48
+jat__pstartd "diag"
49
+    jat_dump__file pxc.out pxc.err
50
+jat__pend
51
+
52
+jat__pstartt "run module set"
53
+    jat__cmd preupg -c FOO/all-xccdf.xml --force
54
+jat__pend