mirror of
https://github.com/aantron/better-enums.git
synced 2025-12-06 16:56:42 +08:00
The documentation is now generated from markdown. Samples are generated from the tutorial pages. Testing is done by a Python script which runs the tests for a large number of compilers. This version is not very developer-friendly - the Python scripts need ways of limiting what compilers they try to run. If you don't have 15 compilers installed, you won't be able to run the tests in this commit. Fix coming soon.
229 lines
6.9 KiB
Python
Executable File
229 lines
6.9 KiB
Python
Executable File
#! /usr/bin/env python
|
|
|
|
import glob
|
|
import os
|
|
import os.path
|
|
import re
|
|
import shutil
|
|
import subprocess
|
|
import sys
|
|
|
|
|
|
|
|
BASE_DIRECTORY = "platform"
|
|
CXXTEST_SOURCE = "cxxtest/tests.h"
|
|
CXXTEST_GENERATED = "cxxtest/tests.cc"
|
|
|
|
quiet = True
|
|
|
|
|
|
|
|
def file_title(path):
|
|
return os.path.splitext(os.path.basename(path))[0]
|
|
|
|
|
|
|
|
expected_example_outputs = {}
|
|
|
|
def load_expected_outputs():
|
|
files = glob.glob("expect/*")
|
|
for file in files:
|
|
stream = open(file)
|
|
try:
|
|
content = stream.read()
|
|
finally:
|
|
stream.close()
|
|
|
|
expected_example_outputs[file_title(file)] = content
|
|
|
|
|
|
|
|
def run(command, catch_warnings = False):
|
|
if not quiet:
|
|
print command
|
|
|
|
try:
|
|
output = subprocess.check_output(command.split(),
|
|
stderr = subprocess.STDOUT)
|
|
|
|
if not catch_warnings:
|
|
return output
|
|
else:
|
|
if re.search("warning", output) != None:
|
|
raise subprocess.CalledProcessError(0, command, output)
|
|
return output
|
|
|
|
except subprocess.CalledProcessError as e:
|
|
print e.output
|
|
print command, "failed"
|
|
sys.exit(1)
|
|
|
|
|
|
|
|
class Configuration(object):
|
|
def __init__(self, subdirectory, command, skip_examples = []):
|
|
self._subdirectory = subdirectory
|
|
self._command = command
|
|
self._skip_examples = skip_examples
|
|
|
|
def elaborate(self, include, output, source):
|
|
command = self._command
|
|
if command.startswith("clang") or command.startswith("g++"):
|
|
return "%s -I%s -Wall -o %s %s" % (command, include, output, source)
|
|
else:
|
|
raise Error("unrecognized compiler in '%s'" % command)
|
|
|
|
def make_directories(self):
|
|
base = self.directory()
|
|
directories = \
|
|
[base,
|
|
os.path.join(base, "example"),
|
|
os.path.join(base, "cxxtest"),
|
|
os.path.join(base, "link"),
|
|
os.path.join(base, "performance")]
|
|
|
|
for directory in directories:
|
|
if not os.path.lexists(directory):
|
|
os.makedirs(directory)
|
|
|
|
def make_all(self):
|
|
print self._command
|
|
|
|
self.make_directories()
|
|
|
|
base = self.directory()
|
|
|
|
examples = glob.glob("../example/*.cc")
|
|
example_directory = os.path.join(base, "example")
|
|
for file in examples:
|
|
title = file_title(file)
|
|
|
|
if title in self._skip_examples:
|
|
continue
|
|
|
|
if title not in expected_example_outputs:
|
|
print "no expected output for example", title
|
|
sys.exit(1)
|
|
|
|
binary = os.path.join(example_directory, title) + ".exe"
|
|
|
|
command = self.elaborate("..", binary, file)
|
|
run(command, True)
|
|
|
|
output = run(binary)
|
|
if output != expected_example_outputs[title]:
|
|
print output
|
|
print "output does not match expected output"
|
|
sys.exit(1)
|
|
|
|
cxxtest_binary = os.path.join(base, "cxxtest", "tests.exe")
|
|
command = self.elaborate("..", cxxtest_binary, CXXTEST_GENERATED)
|
|
run(command, True)
|
|
run(cxxtest_binary)
|
|
|
|
link_sources = glob.glob("link/*.cc")
|
|
link_binary = os.path.join(base, "link", "link.exe")
|
|
command = self.elaborate("..", link_binary, " ".join(link_sources))
|
|
run(command, True)
|
|
|
|
performance_sources = glob.glob("performance/*.cc")
|
|
performance_directory = os.path.join(base, "performance")
|
|
for file in performance_sources:
|
|
title = file_title(file)
|
|
|
|
binary = os.path.join(performance_directory, title) + ".exe"
|
|
|
|
command = "time " + self.elaborate("..", binary, file)
|
|
output = run(command, True)
|
|
|
|
output_file = os.path.join(performance_directory, title) + ".times"
|
|
stream = open(output_file, "w")
|
|
try:
|
|
stream.write(output)
|
|
finally:
|
|
stream.close()
|
|
|
|
def directory(self):
|
|
return os.path.join(BASE_DIRECTORY, self._subdirectory)
|
|
|
|
|
|
|
|
skip_cxx98 = ["101-special-values", "102-bitset", "103-quine", "7-constexpr"]
|
|
skip_strict = ["4-switch"]
|
|
|
|
def modern_gnu(command):
|
|
return [
|
|
Configuration(command + "-c++11", command + " -std=c++11"),
|
|
Configuration(command + "-strict-conversion",
|
|
command + " -std=c++11 " +
|
|
"-DBETTER_ENUMS_STRICT_CONVERSION", skip_strict),
|
|
Configuration(command + "-all-constexpr",
|
|
command + " -std=c++11 " +
|
|
"-DBETTER_ENUMS_CONSTEXPR_TO_STRING"),
|
|
Configuration(command + "-c++98", command + " -std=c++98", skip_cxx98)
|
|
]
|
|
|
|
# g++46 should be one of these, but g++46 c++11 mode currently not supported due
|
|
# to the presence of this bug and lack of a workaround in enum.h.
|
|
# https://gcc.gnu.org/bugzilla/show_bug.cgi?id=54086
|
|
def older_gnu(command):
|
|
return [
|
|
Configuration(command + "-c++0x", command + " -std=c++0x"),
|
|
Configuration(command + "-strict-conversion",
|
|
command + " -std=c++0x " +
|
|
"-DBETTER_ENUMS_STRICT_CONVERSION", skip_strict),
|
|
Configuration(command + "-all-constexpr",
|
|
command + " -std=c++0x " +
|
|
"-DBETTER_ENUMS_CONSTEXPR_TO_STRING"),
|
|
Configuration(command + "-c++98", command + " -std=c++98", skip_cxx98)
|
|
]
|
|
|
|
def gnu_pre_constexpr(command):
|
|
return [
|
|
Configuration(command + "-c++0x-noconstexpr-war",
|
|
command + " -std=c++0x " +
|
|
"-DBETTER_ENUMS_NO_CONSTEXPR", skip_cxx98),
|
|
Configuration(command + "-strict-conversion",
|
|
command + " -std=c++0x " +
|
|
"-DBETTER_ENUMS_NO_CONSTEXPR " +
|
|
"-DBETTER_ENUMS_STRICT_CONVERSION",
|
|
skip_cxx98 + skip_strict),
|
|
Configuration(command + "-c++98", command + " -std=c++98", skip_cxx98)
|
|
]
|
|
|
|
def gnu_pre_enum_class(command):
|
|
return [
|
|
Configuration(command + "-c++0x-noconstexpr-war",
|
|
command + " -std=c++0x " +
|
|
"-DBETTER_ENUMS_NO_CONSTEXPR", skip_cxx98),
|
|
Configuration(command + "-c++98", command + " -std=c++98", skip_cxx98)
|
|
]
|
|
|
|
CONFIGURATIONS = \
|
|
modern_gnu("clang++36") + \
|
|
modern_gnu("clang++35") + \
|
|
modern_gnu("clang++34") + \
|
|
modern_gnu("clang++33") + \
|
|
modern_gnu("g++51") + \
|
|
modern_gnu("g++49") + \
|
|
modern_gnu("g++48") + \
|
|
modern_gnu("g++47") + \
|
|
gnu_pre_constexpr("g++46") + \
|
|
gnu_pre_constexpr("g++45") + \
|
|
gnu_pre_constexpr("g++44") + \
|
|
gnu_pre_enum_class("g++43")
|
|
|
|
|
|
|
|
def main():
|
|
load_expected_outputs()
|
|
|
|
run("cxxtestgen --error-printer -o %s %s" %
|
|
(CXXTEST_GENERATED, CXXTEST_SOURCE))
|
|
|
|
for configuration in CONFIGURATIONS:
|
|
configuration.make_all()
|
|
|
|
if __name__ == "__main__":
|
|
main()
|