. "$BST_LIB" require cscope cscope/present # cscope's exit status is 0 for a query that matched NOTHING as well as for one # that matched, so every query case asserts on OUTPUT; rc is asserted only where # it is a real contract (missing database, no sources, bad option). has() { case "$3" in *"$2"*) bst_ok "$1" ;; *) bst_notok "$1" "want:'$2' got:'$(_bst_1line "$3")'" ;; esac; } hasnot() { case "$3" in *"$2"*) bst_notok "$1" "unexpected:'$2' in '$(_bst_1line "$3")'" ;; *) bst_ok "$1" ;; esac; } tmp=${TMPDIR:-/tmp}/bst-cscope.$$ rm -rf "$tmp" mkdir -p "$tmp/sub" "$tmp/nodb" "$tmp/nosrc" || { bst_notok cscope/tmpdir "cannot create $tmp"; exit 0; } # Fixture line numbers are asserted below, so keep the layout as it is. cat > "$tmp/util.h" <<'EOF' #ifndef BRINTOS_UTIL_H #define BRINTOS_UTIL_H #define BRINTOS_TAG "brintos-cscope-fixture" extern int g_counter; int compute_sum(int a, int b); void helper_log(const char *msg); #endif EOF cat > "$tmp/util.c" <<'EOF' #include #include "util.h" int g_counter; int compute_sum(int a, int b) { g_counter = g_counter + 1; return a + b; } void helper_log(const char *msg) { g_counter = 0; printf("%s: %s\n", BRINTOS_TAG, msg); } EOF cat > "$tmp/main.c" <<'EOF' #include #include "util.h" int main(void) { int total = compute_sum(2, 3); helper_log("running"); printf("total=%d counter=%d\n", total, g_counter); return 0; } EOF cat > "$tmp/sub/extra.c" <<'EOF' #include "../util.h" int extra_entry(void) { return compute_sum(1, 1); } EOF cd "$tmp" || { bst_notok cscope/chdir "cannot cd $tmp"; exit 0; } # --- shipped payload --------------------------------------------------------- # `ocs` is the recipe's second binary (contrib/): the database-maintenance # wrapper, installed beside cscope. if [ -f /usr/bin/ocs ]; then bst_ok cscope/ocs-shipped else bst_notok cscope/ocs-shipped "/usr/bin/ocs missing"; fi check cscope/ocs-syntax sh -n /usr/bin/ocs # -V writes the banner to stderr and exits 0. ver=$(cscope -V 2>&1) has cscope/version "version 15.9" "$ver" check_rc cscope/version-rc 0 cscope -V # --- database build ---------------------------------------------------------- check_rc cscope/build-rc 0 cscope -b -R if [ -s cscope.out ]; then bst_ok cscope/db-created else bst_notok cscope/db-created "cscope.out absent or empty"; fi has cscope/db-magic "cscope 15 " "$(dd if=cscope.out bs=1 count=10 2>/dev/null)" sum1=$(cksum < cscope.out) cscope -b -R >/dev/null 2>&1 sum2=$(cksum < cscope.out) check_eq cscope/build-idempotent "$sum1" "$sum2" # --- queries ----------------------------------------------------------------- # -0 every reference to a C symbol: declaration, definition and both call sites. q0=$(cscope -d -L -0 compute_sum 2>&1) has cscope/sym-all-decl "util.h" "$q0" has cscope/sym-all-def "util.c compute_sum" "$q0" has cscope/sym-all-call "main.c main" "$q0" has cscope/sym-all-sub "sub/extra.c extra_entry" "$q0" # -1 the global definition only — one line, and its line number is the fixture's. q1=$(cscope -d -L -1 compute_sum 2>&1) has cscope/sym-def "util.c compute_sum" "$q1" hasnot cscope/sym-def-only "main.c" "$q1" check_eq cscope/def-line 6 "$(printf '%s\n' "$q1" | awk 'NR==1{print $3}')" # -2 functions called BY main; -3 functions CALLING compute_sum. The two are # different index directions, so both are asserted. q2=$(cscope -d -L -2 main 2>&1) has cscope/called-by-sum "compute_sum" "$q2" has cscope/called-by-log "helper_log" "$q2" q3=$(cscope -d -L -3 compute_sum 2>&1) has cscope/calling-main "main.c main" "$q3" has cscope/calling-sub "sub/extra.c extra_entry" "$q3" # -4 plain text search; -6 goes through cscope's own yacc-built egrep engine. q4=$(cscope -d -L -4 brintos-cscope-fixture 2>&1) has cscope/text "util.h" "$q4" q6=$(cscope -d -L -6 'compute_[a-z]+' 2>&1) has cscope/egrep-def "util.c" "$q6" has cscope/egrep-call "main.c" "$q6" q7=$(cscope -d -L -7 util.c 2>&1) has cscope/file "util.c" "$q7" # -8 who #includes a header — both spellings, "util.h" and "../util.h". q8=$(cscope -d -L -8 util.h 2>&1) has cscope/includes-main "main.c" "$q8" has cscope/includes-util "util.c" "$q8" has cscope/includes-sub "sub/extra.c" "$q8" # -9 assignments to a symbol: exactly the two in the fixture, not its reads. q9=$(cscope -d -L -9 g_counter 2>&1) has cscope/assign-inc "util.c compute_sum 8" "$q9" has cscope/assign-zero "util.c helper_log 14" "$q9" check_eq cscope/assign-count 2 "$(printf '%s\n' "$q9" | grep -c 'g_counter')" # a preprocessor symbol is indexed at its #define and at each use qm=$(cscope -d -L -0 BRINTOS_TAG 2>&1) has cscope/macro-def "util.h" "$qm" has cscope/macro-use "util.c helper_log" "$qm" # line mode must not need a terminal — it is the scriptable interface. qt=$( (unset TERM; cscope -d -L -1 helper_log) 2>&1 ) has cscope/no-term "util.c helper_log" "$qt" # --- contracts --------------------------------------------------------------- # a query that matches nothing prints nothing and still exits 0 qn=$(cscope -d -L -1 nosuchsymbol_brintos 2>&1) check_eq cscope/nomatch-empty "" "$qn" check_rc cscope/nomatch-rc 0 cscope -d -L -1 nosuchsymbol_brintos # -d with no database, and -b with no sources, are the two real error paths cd "$tmp/nodb" || exit 0 check_rc cscope/nodb-rc 1 cscope -d -L -0 anything has cscope/nodb-msg "cannot open file" "$(cscope -d -L -0 anything 2>&1)" cd "$tmp/nosrc" || exit 0 check_rc cscope/nosrc-rc 1 cscope -b has cscope/nosrc-msg "no source files found" "$(cscope -b 2>&1)" if [ -f cscope.out ]; then bst_notok cscope/nosrc-nodb "cscope.out written despite no sources" else bst_ok cscope/nosrc-nodb; fi cd "$tmp" || exit 0 check_rc cscope/badopt-rc 1 cscope -Z badopt=$(cscope -Z 2>&1) has cscope/badopt-msg "invalid option" "$badopt" has cscope/usage "Usage: cscope" "$badopt" # --- options ----------------------------------------------------------------- # -f puts the database somewhere else, and queries must read it back from there check_rc cscope/altdb-build 0 cscope -b -R -f myrefs.db if [ -s myrefs.db ]; then bst_ok cscope/altdb-file else bst_notok cscope/altdb-file "myrefs.db absent or empty"; fi has cscope/altdb-query "util.c helper_log" "$(cscope -d -f myrefs.db -L -1 helper_log 2>&1)" # -i restricts the file set: util.c is indexed, sub/extra.c is not printf 'util.c\nmain.c\n' > names.lst check_rc cscope/namefile-build 0 cscope -b -i names.lst -f i.db has cscope/namefile-incl "util.c" "$(cscope -d -f i.db -L -7 util.c 2>&1)" hasnot cscope/namefile-excl "extra.c" "$(cscope -d -f i.db -L -7 extra.c 2>&1)" # source files named directly on the command line, with no cscope.files check_rc cscope/args-build 0 cscope -b -f a.db util.c has cscope/args-query "util.c compute_sum" "$(cscope -d -f a.db -L -1 compute_sum 2>&1)" # -q adds the inverted index. It is the one path that shells out (to `sort`), # so it is covered separately from the default database above. check_rc cscope/invindex-build 0 cscope -b -q -R -f q.db if [ -s q.db.in ] && [ -s q.db.po ]; then bst_ok cscope/invindex-files else bst_notok cscope/invindex-files "q.db.in/q.db.po absent or empty"; fi has cscope/invindex-query "util.c compute_sum" "$(cscope -d -q -f q.db -L -1 compute_sum 2>&1)" cd / rm -rf "$tmp"