Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
688 changes: 347 additions & 341 deletions testlib.h

Large diffs are not rendered by default.

46 changes: 46 additions & 0 deletions tests/scripts/shadow-flags
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
#!/bin/bash
# Shadowing diagnostics for the compiler in $CPP. Source this file from a test's run.sh.
#
# Sets:
# SHADOW_PROFILE gcc, clang-extended, clang-base or msvc
# SHADOW_WARN_FLAGS flags that enable the shadowing warnings
# SHADOW_ERROR_FLAGS flags that enable them as errors
#
# cl.exe reads its options from the CL environment variable as well (tests/scripts/compile does
# not pass CPP_OPTS to cl.exe), so the MSVC flags can be given either way. MSVC has no -Wshadow:
# C4456/C4457/C4458/C4459 are its warnings for a local, a parameter, a member and a global hidden
# by a declaration.

if [[ -z "$CPP" ]]; then
echo "Must provide CPP in environment"
exit 1
fi

if [[ "$CPP" == "cl.exe" ]]; then
SHADOW_PROFILE="msvc"
# Dashes, not slashes: MSYS would take "/we4456" for a path and convert it.
SHADOW_WARN_FLAGS="-w14456 -w14457 -w14458 -w14459"
SHADOW_ERROR_FLAGS="-we4456 -we4457 -we4458 -we4459"
else
if [[ "$("$CPP" --version 2>&1)" == *clang* ]]; then
shadow_flags_probe="shadow-flags-probe-$$.cpp"
echo "int main() { return 0; }" > "$shadow_flags_probe"
# -Wshadow-all (clang 3.9+) adds constructor parameters and other cases to -Wshadow.
if "$CPP" -Wshadow-all -Werror -fsyntax-only "$shadow_flags_probe" >/dev/null 2>&1; then
SHADOW_PROFILE="clang-extended"
SHADOW_WARN_FLAGS="-Wshadow-all"
SHADOW_ERROR_FLAGS="-Wshadow-all -Werror=shadow-all"
else
SHADOW_PROFILE="clang-base"
SHADOW_WARN_FLAGS="-Wshadow"
SHADOW_ERROR_FLAGS="-Wshadow -Werror=shadow"
fi
rm -f "$shadow_flags_probe"
else
SHADOW_PROFILE="gcc"
SHADOW_WARN_FLAGS="-Wshadow"
SHADOW_ERROR_FLAGS="-Wshadow -Werror=shadow"
fi
fi

export SHADOW_PROFILE SHADOW_WARN_FLAGS SHADOW_ERROR_FLAGS
24 changes: 23 additions & 1 deletion tests/test-000_compile-all-cpp/run.sh
Original file line number Diff line number Diff line change
@@ -1,12 +1,34 @@
#!/bin/bash
set -eo pipefail

# The examples (checkers, validators, generators, interactors) must also compile without
# shadowing diagnostics, both in their own code and in testlib.h. Other .cpp files keep the
# usual flags.
source ../scripts/shadow-flags
echo "Shadowing diagnostics for the examples: $SHADOW_PROFILE ($SHADOW_ERROR_FLAGS)"

(
IFS='
'
examples=0
for f in $(find "$TESTS_DIR"/.. -name "*.cpp"); do
if [[ ! "$f" == *../tests/* ]]; then
bash ../scripts/compile "$f" --check-only
if [[ "$f" == "$TESTS_DIR"/../checkers/* || "$f" == "$TESTS_DIR"/../validators/* ||
"$f" == "$TESTS_DIR"/../generators/* || "$f" == "$TESTS_DIR"/../interactors/* ]]; then
if [[ "$CPP" == "cl.exe" ]]; then
CL="${CL:+$CL }$SHADOW_ERROR_FLAGS" bash ../scripts/compile "$f" --check-only
else
CPP_OPTS="$CPP_OPTS $SHADOW_ERROR_FLAGS" bash ../scripts/compile "$f" --check-only
fi
examples=$((examples + 1))
else
bash ../scripts/compile "$f" --check-only
fi
fi
done
echo "Compiled $examples examples with shadowing diagnostics as errors"
if [[ "$examples" -eq 0 ]]; then
echo "No examples found"
exit 1
fi
)
4 changes: 4 additions & 0 deletions tests/test-004_use-test.h/refs/r1/stderr
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ FAIL Token parameter [name=n] equals to "abacab", doesn't correspond to pattern
FAIL Token parameter [name=n] equals to "abacabaa", doesn't correspond to pattern "a|test|abacaba|ok|abac" (based on )
FAIL Token parameter [name=n] equals to "abacaba!", doesn't correspond to pattern "a|test|abacaba|ok|abac" (based on )
FAIL Integer element a[4] equals to 4, violates the range [1, 3] (based on )
wrong output format Output file not found: "test-004-missing.tmp"
FAIL Answer file not found: "test-004-missing.tmp"
FAIL pattern: Illegal pattern (or part) "ab)"
FAIL Expected integer, but "" found ()
FAIL Expected integer, but "-" found ()
FAIL Expected integer, but "+" found ()
Expand Down Expand Up @@ -51,3 +54,4 @@ FAIL Expected unsigned integer, but "1 2" found ()
FAIL Expected unsigned integer, but "-0" found ()
FAIL Expected unsigned integer, but "--0" found ()
FAIL Expected unsigned integer, but "-00" found ()
FAIL Unexpected encoding for setAppesModeEncoding(encoding)
6 changes: 5 additions & 1 deletion tests/test-004_use-test.h/refs/r1/stdout
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,12 @@ Running test 'split'
Running test 'tokenize' OK
Running test 'opts' OK
Running test 'instream' OK
Running test 'instream_init_sets_mode' OK
Running test 'pattern' OK
Running test 'pattern_src_and_errors' OK
Running test 'stringToLongLong' OK
Running test 'stringToUnsignedLongLong' OK
Running test 'appes_mode_encoding' OK
Running test 'constructors' OK

SUCCESS 8 tests passed.
SUCCESS 12 tests passed.
2 changes: 2 additions & 0 deletions tests/test-004_use-test.h/test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ using namespace std;
#include "tests/test-pattern.cpp"
#include "tests/test-stringToLongLong.cpp"
#include "tests/test-stringToUnsignedLongLong.cpp"
#include "tests/test-appes-mode-encoding.cpp"
#include "tests/test-constructors.cpp"

int main() {
disableFinalizeGuard();
Expand Down
16 changes: 16 additions & 0 deletions tests/test-004_use-test.h/tests/test-appes-mode-encoding.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
TEST(appes_mode_encoding) {
ensure(appesModeEncoding == "windows-1251");

setAppesModeEncoding("UTF-8");
ensure(appesModeEncoding == "utf-8");

setAppesModeEncoding("koi8-r");
ensure(appesModeEncoding == "koi8-r");

// A rejected encoding fails and leaves the current value unchanged.
ensure_exit(3, [](){setAppesModeEncoding("Bad-Enc");});
ensure(appesModeEncoding == "koi8-r");

setAppesModeEncoding("windows-1251");
ensure(appesModeEncoding == "windows-1251");
}
60 changes: 60 additions & 0 deletions tests/test-004_use-test.h/tests/test-constructors.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
TEST(constructors) {
{
ValidatorBoundsHit h;
ensure(!h.minHit && !h.maxHit);
ValidatorBoundsHit hMin(true);
ensure(hMin.minHit && !hMin.maxHit);
ValidatorBoundsHit h00(false, false);
ensure(!h00.minHit && !h00.maxHit);
ValidatorBoundsHit h01(false, true);
ensure(!h01.minHit && h01.maxHit);
ValidatorBoundsHit h10(true, false);
ensure(h10.minHit && !h10.maxHit);
ValidatorBoundsHit h11(true, true);
ensure(h11.minHit && h11.maxHit);
}
{
ensure(exit_exception(0).getExitCode() == 0);
ensure(exit_exception(3).getExitCode() == 3);
ensure(exit_exception(7).getExitCode() == 7);
}
{
const char *path = "test-004-readers.tmp";
std::FILE *out = std::fopen(path, "wb");
ensure(out != NULL);
std::fputs("ab\nc", out);
std::fclose(out);

std::FILE *in = std::fopen(path, "rb");
ensure(in != NULL);
FileInputStreamReader reader(in, "name-1");
ensure(reader.getName() == "name-1");
ensure(reader.getLine() == 1);
ensure(reader.curChar() == 'a');
ensure(reader.nextChar() == 'a');
ensure(reader.nextChar() == 'b');
ensure(reader.nextChar() == '\n');
ensure(reader.getLine() == 2);
ensure(reader.nextChar() == 'c');
ensure(reader.nextChar() == EOFC);
ensure(reader.eof());
reader.close();

in = std::fopen(path, "rb");
ensure(in != NULL);
BufferedFileInputStreamReader buffered(in, "name-2");
ensure(buffered.getName() == "name-2");
ensure(buffered.getLine() == 1);
ensure(buffered.curChar() == 'a');
ensure(buffered.nextChar() == 'a');
ensure(buffered.nextChar() == 'b');
ensure(buffered.nextChar() == '\n');
ensure(buffered.getLine() == 2);
ensure(buffered.nextChar() == 'c');
ensure(buffered.nextChar() == EOFC);
ensure(buffered.eof());
buffered.close();

std::remove(path);
}
}
39 changes: 39 additions & 0 deletions tests/test-004_use-test.h/tests/test-instream.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,3 +53,42 @@ TEST(instream) {
ensure(s.eof());
}
}

TEST(instream_init_sets_mode) {
const char *path = "test-004-init.tmp";
const char *missing = "test-004-missing.tmp";
std::FILE *out = std::fopen(path, "wb");
ensure(out != NULL);
std::fputs("12 ab\n", out);
std::fclose(out);

const TMode modes[] = {_input, _output, _answer};
for (size_t i = 0; i < sizeof(modes) / sizeof(modes[0]); i++) {
{
InStream s;
s.init(path, modes[i]);
ensure(s.mode == modes[i]);
ensure(s.readInt() == 12);
}
{
std::FILE *in = std::fopen(path, "rb");
ensure(in != NULL);
InStream s;
s.init(in, modes[i]);
ensure(s.mode == modes[i]);
ensure(s.readToken() == "12");
}
}

// The mode is set before the file is opened: a missing file is not an error for input,
// a presentation error for output and a failure for answer.
{
InStream s;
s.init(missing, _input);
ensure(s.mode == _input);
}
ensure_exit(2, [&](){InStream s; s.init(missing, _output);});
ensure_exit(3, [&](){InStream s; s.init(missing, _answer);});

std::remove(path);
}
15 changes: 15 additions & 0 deletions tests/test-004_use-test.h/tests/test-pattern.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,3 +38,18 @@ TEST(pattern) {
ensure(!pattern("oo(x(aa|ba)|y(ac|dd))|yes").matches("ooyddd"));
}
}

TEST(pattern_src_and_errors) {
// src() returns the pattern as given; spaces are dropped only for matching.
ensure(pattern(" [a-c] {2} ").src() == " [a-c] {2} ");
ensure(pattern(" [a-c] {2} ").matches("ab"));
ensure(!pattern(" [a-c] {2} ").matches(" ab"));
ensure(pattern("No solution").src() == "No solution");
ensure(pattern("No solution").matches("Nosolution"));
ensure(!pattern("No solution").matches("No solution"));
ensure(pattern("No\\ solution").src() == "No\\ solution");
ensure(pattern("No\\ solution").matches("No solution"));
ensure(!pattern("No\\ solution").matches("Nosolution"));
// The error message shows the pattern without spaces: "ab)".
ensure_exit(3, [](){pattern("a b)");});
}
13 changes: 13 additions & 0 deletions tests/test-011_shadow/files/fixture-constructor.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// A constructor parameter hides a data member: diagnosed by GCC and Clang -Wshadow-all,
// MSVC does not diagnose it.
#include "testlib.h"

struct Counter {
int count;
explicit Counter(int count) : count(count) {}
};

int main() {
Counter counter(0);
return counter.count;
}
9 changes: 9 additions & 0 deletions tests/test-011_shadow/files/fixture-global.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// A local variable hides a global variable of the program: must still be diagnosed after testlib.h.
#include "testlib.h"

int value = 0;

int main() {
int value = 1;
return value;
}
11 changes: 11 additions & 0 deletions tests/test-011_shadow/files/fixture-local.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// A local variable hides another local variable: must still be diagnosed after testlib.h.
#include "testlib.h"

int main() {
int count = 0;
{
int count = 1;
(void)count;
}
return count;
}
16 changes: 16 additions & 0 deletions tests/test-011_shadow/files/fixture-member.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// A method parameter hides a data member: diagnosed by GCC and Clang. With MSVC, testlib.h
// disables C4458 for the rest of the translation unit, and that is not changed.
#include "testlib.h"

struct Counter {
int count;
void set(int count) {
this->count = count;
}
};

int main() {
Counter counter;
counter.set(0);
return counter.count;
}
13 changes: 13 additions & 0 deletions tests/test-011_shadow/files/fixture-parameter.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// A local variable hides a function parameter: must still be diagnosed after testlib.h.
#include "testlib.h"

int twice(int count) {
{
int count = 2;
return count;
}
}

int main() {
return twice(0);
}
20 changes: 20 additions & 0 deletions tests/test-011_shadow/files/fixture-user-globals.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// Globals of a program, declared after testlib.h, then the templates of testlib.h are instantiated.
// MSVC checks a template body where it is instantiated, and Clang with delayed template parsing (the
// default for the MSVC target before C++20) checks the parameters there as well, so a local or a
// parameter of a testlib template named like one of these globals would be reported in testlib.h.
// The list holds the names those locals and parameters had before they got the "_" prefix, and names
// that programs commonly use. ("index" is left out: glibc declares a function of that name.)
#include "testlib.h"
#include <list>
#include <set>

int about, ap, buffer, current, d, digit, expected, expectedString, first, foundString, i, it, message,
n, n_, negative, p, pos, preparedVariableName, prepend, repeated, result, result_sum, s, septums, sign,
size, ss, sum_, t_string, trailingZeroCount, vals, value, written, x;
int a, args, b, begin, c, collection, default_value, end, fmt, found, from, key, last, lower, min_part,
nonnegative, points, prependFormat, s_, separator, t, to, type, upper, variableName;
int e, f, g, h, j, k, l, m, q, r, u, v, w, y, z;
int N, M, K, INF, MOD, MAXN, cnt, len, res, sum, total, answer, mx, mn, dp, cur, ok, used, adj, edges, tmp,
lo, hi, mid, mod, count, rest, text;

#include "shadow-probe.cpp"
31 changes: 31 additions & 0 deletions tests/test-011_shadow/files/shadow-api.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// Compile-only probe: the signatures and default arguments of the functions whose parameters
// were renamed to avoid shadowing stay the same.
#include "testlib.h"

int main() {
bool (pattern::*matches1)(const std::string &) const = &pattern::matches;
void (InStream::*init1)(std::string, TMode) = &InStream::init;
void (InStream::*init2)(std::FILE *, TMode) = &InStream::init;
void (*setter)(std::string) = &setAppesModeEncoding;
(void)matches1;
(void)init1;
(void)init2;
(void)setter;

pattern p("[a-z]+");
(void)p;

ValidatorBoundsHit h0;
ValidatorBoundsHit h1(true);
ValidatorBoundsHit h2(true, false);
bool hits = h0.minHit || h0.maxHit || h1.minHit || h2.maxHit;
(void)hits;

if (false) {
FileInputStreamReader file(stdin, "stdin");
BufferedFileInputStreamReader buffered(stdin, "stdin");
(void)file.getName();
(void)buffered.getName();
}
return 0;
}
Loading
Loading