├── .gitignore ├── levenshtein └── sample │ ├── info.txt │ ├── sample.cpp │ └── sample_ok.cpp ├── measure.py ├── oneshot └── sample │ ├── includes.txt │ ├── info.txt │ └── sample.cpp ├── participating.txt ├── precision └── sample │ ├── info.txt │ └── sample.cpp └── readme.txt /.gitignore: -------------------------------------------------------------------------------- 1 | .project 2 | .pydevproject 3 | 4 | -------------------------------------------------------------------------------- /levenshtein/sample/info.txt: -------------------------------------------------------------------------------- 1 | email foo@example.com 2 | title Simple sample 3 | author My Name 4 | -------------------------------------------------------------------------------- /levenshtein/sample/sample.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | using namespace std; 5 | int main(int, char **argv) { 6 | ifstream t(argv[1]); 7 | stringstream s; 8 | s << t.rdbuf(); 9 | auto i = s.str(); 10 | string j(i.rbegin(), i.rend()); 11 | ofstream o(argv[2]); 12 | o << j; 13 | return 0 14 | } 15 | -------------------------------------------------------------------------------- /levenshtein/sample/sample_ok.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | using namespace std; 5 | int main(int, char **argv) { 6 | ifstream t(argv[1]); 7 | stringstream s; 8 | s << t.rdbuf(); 9 | auto i = s.str(); 10 | string j(i.rbegin(), i.rend()); 11 | ofstream o(argv[2]); 12 | o << j; 13 | return 0; 14 | } 15 | -------------------------------------------------------------------------------- /measure.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # Copyright (C) 2013 Jussi Pakkanen 4 | # 5 | # Authors: 6 | # Jussi Pakkanen 7 | # 8 | # This library is free software; you can redistribute it and/or modify it under 9 | # the terms of version 3 of the GNU General Public License as published 10 | # by the Free Software Foundation. 11 | # 12 | # This library is distributed in the hope that it will be useful, but WITHOUT 13 | # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 14 | # FOR A PARTICULAR PURPOSE. See the GNU General Public License for more 15 | # details. 16 | # 17 | # You should have received a copy of the GNU General Public License 18 | # along with this program. If not, see . 19 | 20 | from glob import glob 21 | import os 22 | import subprocess 23 | import re 24 | import random 25 | import Levenshtein 26 | import math 27 | 28 | random.seed() 29 | 30 | precision_target = int(math.pi*1024*1024) 31 | 32 | def precisionchecker(infile): 33 | if len(open(infile, 'rb').read()) > 256: 34 | print('Source file', infile, 'too long.') 35 | return False 36 | return True 37 | 38 | def plainchecker(infile): 39 | permitted = {'vector' : True, 40 | 'map' : True, 41 | 'iostream' : True, 42 | 'functional' : True, 43 | 'memory' : True, 44 | 'utility' : True, 45 | 'stdexcept' : True, 46 | 'string' : True, 47 | 'set' : True, 48 | 'unordered_map' : True, 49 | 'unordered_set' : True, 50 | 'regex' : True, 51 | 'array' : True, 52 | 'stack' : True, 53 | 'queue' : True, 54 | 'algorithm' : True, 55 | 'iterator' : True, 56 | 'complex' : True, 57 | 'atomic' : True, 58 | 'thread' : True, 59 | 'mutex' : True, 60 | 'future' : True, 61 | 'typeinfo' : True, 62 | 'tuple' : True, 63 | 'initializer_list' : True 64 | } 65 | if len(open(infile, 'rb').read()) > 512: 66 | print('Source file', infile, 'too long.') 67 | includere = re.compile('''^\s*#\s*include\s*[<"](.*?)[>"]''') 68 | for line in open(infile): 69 | m = re.search(includere, line) 70 | if m: 71 | include = m.group(1) 72 | if include not in permitted: 73 | print("Invalid include", include, "in", infile) 74 | return False 75 | elif '#' in line or '??=' in line or '%:' in line or line.strip().endswith('%\\'): 76 | print('Invalid use of preprocessor in', infile) 77 | return False 78 | return True 79 | 80 | def oneshotchecker(infile): 81 | if len(open(infile, 'rb').read()) > 256: 82 | print('Source file', infile, 'too long.') 83 | return False 84 | return True 85 | 86 | def create_testdata(): 87 | res = [] 88 | for i in range(random.randint(1000, 10000)): 89 | res.append(chr(ord('a') + random.randint(0, 26))) 90 | if random.random() < 0.1: 91 | res.append('\n') 92 | return ''.join(res) 93 | 94 | def levenshteinchecker(infile): 95 | (base, suf) = os.path.splitext(infile) 96 | okfile = base + '_ok' + suf 97 | if not os.path.exists(okfile): 98 | print('Passing file', okfile, 'not found.') 99 | return False 100 | entry_src = open(infile, 'rb').read() 101 | if len(entry_src) > 256: 102 | print('Source file too big.') 103 | return False 104 | dist = Levenshtein.distance(entry_src, open(okfile, 'rb').read()) 105 | if dist != 1: 106 | print('Levenshtein distance', dist, 'not equal to one.') 107 | return False 108 | binname = os.path.join(os.path.curdir, 'levbinary') 109 | cmd = ['g++', '-std=c++11', '-Wall', '-Wextra', '-Wpedantic', '-o', binname, okfile] 110 | p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) 111 | if b'//' in entry_src or b'/*' in entry_src: 112 | print("Comments are forbidden in this category. Nice try, though.") 113 | return False 114 | (stdo, stde) = p.communicate() 115 | stdo = stdo.decode() 116 | stde = stde.decode() 117 | if p.returncode != 0: 118 | print("Compilation failed.") 119 | print(stdo) 120 | print(stde) 121 | return False 122 | if len(stdo) != 0: 123 | print("Fail, stdout has text:") 124 | print(stdo) 125 | return False 126 | if len(stde) != 0: 127 | print('Fail, stderr has text:') 128 | print(stde) 129 | return False 130 | testdata = create_testdata() 131 | testifname = 'test.dat' 132 | testofname = 'output.dat' 133 | open(testifname, 'w').write(testdata) 134 | p = subprocess.Popen([binname, testifname, testofname], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) 135 | p.communicate() 136 | if p.returncode != 0: 137 | print("Running test binary failed.") 138 | os.unlink(binname) 139 | os.unlink(testifname) 140 | return False 141 | if not os.path.exists(testofname): 142 | print('Output file not created.') 143 | os.unlink(binname) 144 | os.unlink(testifname) 145 | return False 146 | testoutput = open(testofname, 'r').read() 147 | os.unlink(binname) 148 | os.unlink(testifname) 149 | os.unlink(testofname) 150 | if testoutput[::-1] != testdata: 151 | print("Output is incorrect.") 152 | return False 153 | return True 154 | 155 | def packages_installed(packagefile): 156 | if not os.path.isfile(packagefile): 157 | print('Package file missing in ', packagefile) 158 | for line in open(packagefile).readlines(): 159 | line = line.strip() 160 | if line == '': 161 | continue 162 | cmd = ['aptitude', 'show', line] 163 | pc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) 164 | so = pc.communicate()[0].decode() 165 | if not 'State: installed' in so: 166 | print('Package', line, 'not installed in', packagefile) 167 | return False 168 | return True 169 | 170 | def info_ok(infofile): 171 | if not os.path.isfile(infofile): 172 | print('Info file missing for', infofile) 173 | return False 174 | lines = open(infofile).readlines() 175 | if len(lines) != 3: 176 | print('Incorrect number of lines in info file in', infofile) 177 | return False 178 | elems = lines[0].strip().split() 179 | if len(elems) != 2: 180 | print('Malformed email line in', infofile) 181 | return False 182 | if elems[0] != 'email' or '@' not in elems[1]: 183 | print('Malformed email line in', infofile) 184 | return False 185 | elems = lines[1].strip().split() 186 | if len(elems) < 2 or elems[0] != 'title': 187 | print('Malformed title line in', infofile) 188 | return False 189 | elems = lines[2].strip().split() 190 | if len(elems) < 2 or elems[0] != 'author': 191 | print('Malformed author line in', infofile) 192 | return False 193 | return True 194 | 195 | def has_extra_files(d, basename): 196 | allowed = {'info.txt' : True, 197 | 'includes.txt' : True, 198 | 'packages.txt' : True, 199 | basename + '.cpp': True 200 | } 201 | if os.path.split(d)[0] == 'levenshtein': 202 | allowed[basename + '_ok.cpp'] = True 203 | for d in glob(os.path.join(d, '*')): 204 | base = os.path.split(d)[-1] 205 | if base not in allowed: 206 | print(basename, 'has an extra file', base) 207 | return True 208 | return False 209 | 210 | def measure(subdir): 211 | compiler = '/usr/bin/g++' 212 | basic_flags = ['-std=c++11', '-c', '-o', '/dev/null'] 213 | buildtype_flags = {'oneshot': ['-fmax-errors=1'], 214 | 'levenshtein' : [], 215 | 'precision' : []} 216 | results = [] 217 | include_re = re.compile('[^a-zA-Z0-9/-_.]') 218 | dirname_re = re.compile('[^a-z0-9]') 219 | for d in glob(os.path.join(subdir, '*')): 220 | basename = os.path.split(d)[-1] 221 | if dirname_re.search(basename) is not None: 222 | print("Only lowercase letters and numbers allowed in entry name.") 223 | continue 224 | sourcename = basename + '.cpp' 225 | fullsrc = os.path.join(d, sourcename) 226 | if has_extra_files(d, basename): 227 | continue 228 | if not os.path.isfile(fullsrc): 229 | print('Missing source file', fullsrc) 230 | continue 231 | infofile = os.path.join(d, 'info.txt') 232 | packagefile = os.path.join(d, 'packages.txt') 233 | if subdir == 'anything': 234 | if not packages_installed(packagefile): 235 | continue 236 | else: 237 | if os.path.isfile(packagefile): 238 | print('Package file exists in non-anything dir', basename) 239 | continue 240 | if not info_ok(infofile): 241 | continue 242 | if subdir == 'oneshot': 243 | checker = oneshotchecker 244 | elif subdir == 'levenshtein': 245 | checker = levenshteinchecker 246 | else: 247 | checker = precisionchecker 248 | if not checker(fullsrc): 249 | continue 250 | if not os.path.isfile(fullsrc): 251 | print("Bad file in subdir", d) 252 | continue 253 | cmd_arr = ['(', 'ulimit', '-t', '300', ';',\ 254 | 'ulimit', '-v', '16252928', ';', compiler, "'%s'" % fullsrc] + basic_flags 255 | faulty = False 256 | if subdir == 'oneshot': 257 | includefile = os.path.join(d, 'includes.txt') 258 | for line in open(includefile): 259 | line = line.strip() 260 | if include_re.search(line) is not None: 261 | print('Invalid include dir', line, 'in', d) 262 | faulty = True 263 | break 264 | cmd_arr.append('-I' + line) 265 | if faulty: 266 | continue 267 | cmd_arr += buildtype_flags[subdir] 268 | cmd_arr += [')', '2>&1', '>', '/dev/null', '|', 'wc', '-c'] 269 | cmd = ' '.join(cmd_arr) 270 | # Remember kids, you should not use shell=True unless you 271 | # have a very good reason. We need it to use wc and ulimit. 272 | pc = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) 273 | res = pc.communicate() 274 | stdout = res[0].decode() 275 | input_size = len(open(fullsrc, 'rb').read()) 276 | output_size = int(stdout) 277 | if input_size == 0: 278 | print('Empty input file in subdir', d) 279 | continue 280 | ratio = output_size / input_size 281 | results.append((ratio, input_size, output_size, basename)) 282 | results.sort(reverse=True) 283 | return results 284 | 285 | def run(): 286 | print('The Grand C++ Error Explosion Competition\n') 287 | print('This program will measure entries and print the results (not necessarily in order).\n') 288 | print('The output contains four elements:') 289 | print('ratio, source code size, error message size, name\n') 290 | print('Starting measurements for type oneshot.') 291 | plain_times = measure('oneshot') 292 | print('Table for category oneshot:') 293 | for i in plain_times: 294 | print('%.2f' % i[0], i[1], i[2], i[3]) 295 | 296 | print('\nStarting measurements for type levenshtein.') 297 | lev_times = measure('levenshtein') 298 | print('\nTable for category levenshtein:') 299 | for i in lev_times: 300 | print('%.2f' % i[0], i[1], i[2], i[3]) 301 | 302 | print('\nStarting measurements for type precision.') 303 | print('source code size, delta, name') 304 | prec_times = measure('precision') 305 | print('\nTable for category precision:') 306 | for i in prec_times: 307 | print(i[1], '%d' % abs(precision_target - i[2]), i[3]) 308 | 309 | if __name__ == '__main__': 310 | run() 311 | -------------------------------------------------------------------------------- /oneshot/sample/includes.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jpakkane/tgceec/ec335e2de707a65f8e735f2d338268b19eebc144/oneshot/sample/includes.txt -------------------------------------------------------------------------------- /oneshot/sample/info.txt: -------------------------------------------------------------------------------- 1 | email foo@example.com 2 | title Simple sample 3 | author My Name 4 | -------------------------------------------------------------------------------- /oneshot/sample/sample.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main(int argc, char **argv) { 4 | std::cout << "Something 5 | return 0; 6 | } 7 | -------------------------------------------------------------------------------- /participating.txt: -------------------------------------------------------------------------------- 1 | How to participate 2 | 3 | This documentation describes how to create and submit your entry to 4 | the Grand C++ Error Explosion Competition. The steps below should work 5 | on any Linux platform but the final measurements will be done on a 64 6 | bit install of Ubuntu 14/10 (utopic). Note that the flag -std=c++11 is 7 | used on all entries. It is the submitter's responsibility to test 8 | their submission on the target platform, the organizers will not 9 | provide technical support or intermediary results over email or any 10 | other medium. 11 | 12 | In order to run the test script you ned to first install the Python 13 | Levenshtein package. This can be accomplished with the following 14 | command: 15 | 16 | sudo apt-get install python3-levenshtein 17 | 18 | Then you need to select which category you wish to participate in. For 19 | this example we will use the oneshot category. Create a subdirectory in 20 | the category subdir to store your entry in. It can have any name, but 21 | it is recommended to make it short and relatively unique, such as an 22 | abbreviation of your name. 23 | 24 | mkdir oneshot/bobmcbob 25 | 26 | In this subdirectory create a source file whose name is the same as 27 | the directory and with the suffix cpp. 28 | 29 | touch oneshot/bobmcbob/bobmcbob.cpp 30 | 31 | Create an info file in the subdirectory with your contact info. 32 | It must be called info.txt and contain the following three lines. 33 | 34 | email your@email-address.com 35 | title How you wish your creation to be called 36 | author The name or alias by which you wish to be called 37 | 38 | Your email address will not be published. 39 | 40 | Write your entry in the cpp file. You can inspect your results by 41 | running the measurement script. 42 | 43 | ./measure.py 44 | 45 | If your entry has problems, the script will tell you. 46 | 47 | If you participate in the oneshot category, you need to create two 48 | more files, a package file and include directory file. The package 49 | file contains a list of Ubuntu packages (one per line) that must be 50 | installed in order to compile the code. It is called packages.txt. The 51 | include file lists the directories, also one per line, that must be 52 | put in the search path for your compilation. It is called 53 | includes.txt. 54 | 55 | Each category has a working sample entry. Feel free to use them to create 56 | your version. 57 | 58 | Once your code passes validation it is ready for submission. Zip up your 59 | directory. 60 | 61 | zip -r bobmcbob.zip oneshot/bobmcbob 62 | 63 | Now you can email it to . Note that if you submit an 64 | entry that does not pass the validation check, it will be silently 65 | rejected from the competition. It is your responsibility to verify 66 | that your code passes. The test harness may be updated during the 67 | competition. Submissions that don't pass the updated test harness 68 | will be discarded. It is the responsibility of the participants to 69 | resubmit entries that do not pass the test suite any more. 70 | -------------------------------------------------------------------------------- /precision/sample/info.txt: -------------------------------------------------------------------------------- 1 | email foo@example.com 2 | title Simple sample 3 | author My Name 4 | -------------------------------------------------------------------------------- /precision/sample/sample.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main(int argc, char **argv) { 4 | std::cout < "Something; 5 | return 0; 6 | } 7 | -------------------------------------------------------------------------------- /readme.txt: -------------------------------------------------------------------------------- 1 | This repo contains the testing harness for The 2 | Grand C++ Error Explosion Competition. 3 | 4 | For further info see http://tgceec.tumblr.com. 5 | 6 | --------------------------------------------------------------------------------