1 2""" 3 Copyright Kristjan Kongas 2020 4 5 Boost Software License - Version 1.0 - August 17th, 2003 6 7 Permission is hereby granted, free of charge, to any person or organization 8 obtaining a copy of the software and accompanying documentation covered by 9 this license (the "Software") to use, reproduce, display, distribute, 10 execute, and transmit the Software, and to prepare derivative works of the 11 Software, and to permit third-parties to whom the Software is furnished to 12 do so, all subject to the following: 13 14 The copyright notices in the Software and this entire statement, including 15 the above license grant, this restriction and the following disclaimer, 16 must be included in all copies of the Software, in whole or in part, and 17 all derivative works of the Software, unless such copies or derivative 18 works are solely in the form of machine-executable object code generated by 19 a source language processor. 20 21 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23 FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT 24 SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE 25 FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, 26 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 27 DEALINGS IN THE SOFTWARE. 28""" 29 30import subprocess, json 31from pathlib import Path 32 33fire_failure_code = 1 34 35class assert_runner: 36 test_count = 0 37 check_count = 0 38 39 def __init__(self, pth): 40 self.pth = str(pth) 41 assert_runner.test_count += 1 42 self.help_success("-h") 43 self.help_success("--help") 44 45 def equal(self, cmd, out): 46 stdout, stderr, code = self.run(cmd) 47 assert code == 0 48 assert stdout == self.remove_newline(out.strip()) 49 assert stderr == "" 50 assert_runner.check_count += 1 51 52 def handled_failure(self, cmd): 53 stdout, stderr, code = self.run(cmd) 54 assert code == fire_failure_code 55 assert stdout == "" 56 assert stderr != "" 57 assert_runner.check_count += 1 58 59 def help_success(self, cmd): 60 stdout, stderr, code = self.run(cmd) 61 assert code == 0 62 assert stdout == "" 63 assert stderr != "" 64 assert_runner.check_count += 1 65 66 def run(self, cmd): 67 result = subprocess.run([self.pth] + cmd.split(), stdout=subprocess.PIPE, stderr=subprocess.PIPE) 68 stdout = self.remove_newline(self.b2str(result.stdout.strip())) 69 stderr = self.remove_newline(self.b2str(result.stderr.strip())) 70 code = result.returncode 71 return stdout, stderr, code 72 73 def remove_newline(self, strn): 74 return strn.replace("\r", "").replace("\n", "") 75 76 def b2str(self, b): 77 return str(b, "utf-8") 78 79 80def run_all_combinations(path_prefix): 81 runner = assert_runner(path_prefix / "all_combinations") 82 83 runner.equal("0 -i=0", "") 84 runner.equal("0 1 -i=0 --def-r=0.0 --opt-s=string", "") 85 runner.equal("0 1 -i 0 --def-r 0.0 --opt-s string", "") 86 87 88def run_basic(path_prefix): 89 runner = assert_runner(path_prefix / "basic") 90 91 runner.equal("-x 3 -y 4", "3 + 4 = 7") 92 runner.equal("-x -3 -y 3", "-3 + 3 = 0") 93 runner.equal("-x=-3 -y=3", "-3 + 3 = 0") 94 runner.equal("-x3 -y4", "3 + 4 = 7") 95 runner.handled_failure("") 96 runner.handled_failure("-x 3") 97 runner.handled_failure("-y 4") 98 runner.handled_failure("-x test") 99 runner.handled_failure("-x") 100 runner.handled_failure("--undefined 0") 101 runner.help_success("-x 0 -h") 102 runner.help_success("-h --undefined") 103 104 105def run_flag(path_prefix): 106 runner = assert_runner(path_prefix / "flag") 107 108 runner.equal("", "flag-a: false flag-b: false") 109 runner.equal("-a -b", "flag-a: true flag-b: true") 110 runner.equal("-ab", "flag-a: true flag-b: true") 111 runner.equal("--flag-a", "flag-a: true flag-b: false") 112 runner.equal("--flag-b", "flag-a: false flag-b: true") 113 runner.handled_failure("-a 1") 114 115 116def run_optional_and_default(path_prefix): 117 runner = assert_runner(path_prefix / "optional_and_default") 118 119 runner.equal("", "optional: [no value]\ndefault: 0") 120 runner.equal("--default 1", "optional: [no value]\ndefault: 1") 121 runner.equal("--optional -1", "optional: -1\ndefault: 0") 122 runner.equal("--optional -1 --default 1", "optional: -1\ndefault: 1") 123 124 125def run_positional(path_prefix): 126 runner = assert_runner(path_prefix / "positional") 127 128 runner.handled_failure("") 129 runner.handled_failure("test") 130 runner.equal("2", "2 0") 131 runner.equal("2 3", "2 3") 132 runner.handled_failure("2 3 4") 133 runner.equal("-1 -3", "-1 -3") 134 135 136def run_variadic(path_prefix): 137 runner = assert_runner(path_prefix / "variadic") 138 139 runner.equal("", "\n") 140 runner.equal("b a", "b a\n") 141 runner.equal("b a -o", "b\na\n") 142 runner.equal("b a -s", "a b\n") 143 runner.equal("b a -os", "a\nb\n") 144 runner.equal("a -- -b", "a -b\n") 145 146 147def run_no_exceptions(path_prefix): 148 runner = assert_runner(path_prefix / "no_exceptions") 149 150 runner.equal("", "\n") 151 runner.equal("1 2", "1 2 \n") 152 runner.equal("1 2 -r=2", "1 2 \n1 2 \n") 153 stdout, stderr, code = runner.run("-h") 154 assert stderr.find("Notes") != -1 155 156 157def get_path_prefix(subdir): 158 cur_dir = Path(__file__).absolute().parent 159 with (cur_dir / "build_dirs.json").open("r") as json_file: 160 json_obj = json.load(json_file) 161 return cur_dir / json_obj[subdir] 162 163 164def main(): 165 path_prefix = get_path_prefix("examples") 166 167 print("Running tests in {} ...".format(path_prefix), end="") 168 169 run_all_combinations(path_prefix) 170 run_basic(path_prefix) 171 run_flag(path_prefix) 172 run_optional_and_default(path_prefix) 173 run_positional(path_prefix) 174 run_variadic(path_prefix) 175 176 run_no_exceptions(path_prefix) 177 178 print(" SUCCESS! (ran {} tests with {} checks)".format(assert_runner.test_count, assert_runner.check_count)) 179 180 181if __name__ == "__main__": 182 main() 183