add environment funcs (environ.hh) and update test runner code (less verbose/cleaner)

This commit is contained in:
q66 2016-03-13 01:28:39 +00:00
parent 3c708e780d
commit 40746de1c3
2 changed files with 107 additions and 57 deletions

62
ostd/environ.hh Normal file
View file

@ -0,0 +1,62 @@
/* Environment handling.
*
* This file is part of OctaSTD. See COPYING.md for futher information.
*/
#ifndef OSTD_ENVIRON_HH
#define OSTD_ENVIRON_HH
#include <stdlib.h>
#include <string.h>
#include "ostd/maybe.hh"
#include "ostd/string.hh"
namespace ostd {
namespace environ {
inline Maybe<ConstCharRange> get(ConstCharRange name) {
char buf[256];
const char *ret = nullptr;
if (name.size() < sizeof(buf)) {
memcpy(buf, name.data(), name.size());
buf[name.size()] = '\0';
ret = getenv(buf);
} else {
ret = getenv(String(name).data());
}
if (!ret) return ostd::nothing;
return ostd::move(ConstCharRange(ret));
}
inline bool set(ConstCharRange name, ConstCharRange value,
bool update = true) {
char sbuf[2048];
char *buf = sbuf;
bool alloc = (name.size() + value.size() + 2) > sizeof(sbuf);
if (alloc)
buf = new char[name.size() + value.size() + 2];
memcpy(buf, name.data(), name.size());
buf[name.size()] = '\0';
memcpy(&buf[name.size() + 1], value.data(), value.size());
buf[name.size() + value.size() + 1] = '\0';
bool ret = !setenv(buf, &buf[name.size() + 1], update);
if (alloc)
delete[] buf;
return ret;
}
inline bool unset(ConstCharRange name) {
char buf[256];
if (name.size() < sizeof(buf)) {
memcpy(buf, name.data(), name.size());
buf[name.size()] = '\0';
return !unsetenv(buf);
}
return !unsetenv(String(name).data());
}
} /* namespace environ */
} /* namespace ostd */
#endif

View file

@ -1,102 +1,90 @@
#include <stdio.h>
#include <stdlib.h>
#include <ostd/platform.hh> #include <ostd/platform.hh>
#include <ostd/io.hh> #include <ostd/io.hh>
#include <ostd/string.hh> #include <ostd/string.hh>
#include <ostd/map.hh> #include <ostd/map.hh>
#include <ostd/filesystem.hh> #include <ostd/filesystem.hh>
#include <ostd/environ.hh>
using namespace ostd; using namespace ostd;
ConstCharRange get_env(ConstCharRange var, ConstCharRange def = nullptr) { #ifndef OSTD_PLATFORM_WIN32
const char *ret = getenv(String(var).data()); constexpr auto ColorRed = "\033[91m";
if (!ret || !ret[0]) constexpr auto ColorGreen = "\033[92m";
return def; constexpr auto ColorBlue = "\033[94m";
return ret; constexpr auto ColorBold = "\033[1m";
} constexpr auto ColorEnd = "\033[0m";
#else
constexpr auto ColorRed = "";
constexpr auto ColorGreen = "";
constexpr auto ColorBlue = "";
constexpr auto ColorBold = "";
constexpr auto ColorEnd = "";
#endif
int main() { int main() {
ConstCharRange compiler = get_env("CXX", "c++"); /* configurable section */
ConstCharRange cxxflags = "-std=c++14 -Wall -Wextra -Wshadow "
"-Wno-missing-braces " /* clang false positive */
"-I.";
ConstCharRange testdir = get_env("TESTDIR", "tests");
ConstCharRange srcext = ".cc";
Map<ConstCharRange, ConstCharRange> colors = { auto compiler = environ::get("CXX").value_or("c++");
#ifndef OSTD_PLATFORM_WIN32 auto cxxflags = "-std=c++14 -Wall -Wextra -Wshadow "
{ "red", "\033[91m" }, "-Wno-missing-braces " /* clang false positive */
{ "green", "\033[92m" }, "-I.";
{ "blue", "\033[94m" }, auto testdir = environ::get("TESTDIR").value_or("tests");
{ "bold", "\033[1m" }, auto srcext = ".cc";
{ "end", "\033[0m" }
#else auto userflags = environ::get("CXXFLAGS").value_or("");
{ "red", "" },
{ "green", "" }, /* do not change past this point */
{ "blue", "" },
{ "bold", "" },
{ "end", "" }
#endif
};
ConstCharRange userflags = get_env("CXXFLAGS", "");
int nsuccess = 0, nfailed = 0; int nsuccess = 0, nfailed = 0;
ConstCharRange modname = nullptr;
auto print_result = [&colors, &nsuccess, &nfailed] auto print_result = [&](ConstCharRange fmsg = nullptr) {
(ConstCharRange modname, ConstCharRange fmsg = nullptr) {
write(modname, "...\t"); write(modname, "...\t");
if (!fmsg.empty()) { if (!fmsg.empty()) {
writeln(colors["red"], colors["bold"], "(", fmsg, ")", colors["end"]); writeln(ColorRed, ColorBold, "(", fmsg, ")", ColorEnd);
++nfailed; ++nfailed;
} else { } else {
writeln(colors["green"], colors["bold"], "(success)", colors["end"]); writeln(ColorGreen, ColorBold, "(success)", ColorEnd);
++nsuccess; ++nsuccess;
} }
}; };
DirectoryStream ds(testdir); DirectoryStream ds(testdir);
for (auto v: ds.iter()) { for (auto v: ds.iter()) {
if (v.type() != FileType::regular) if ((v.type() != FileType::regular) || (v.extension() != srcext))
continue;
if (v.extension() != srcext)
continue; continue;
modname = v.stem();
String exepath = testdir; String exepath = testdir;
exepath += PathSeparator; exepath += PathSeparator;
exepath += v.stem(); exepath += modname;
String cxxcmd = compiler; auto cxxcmd = appender<String>();
cxxcmd += " "; format(cxxcmd, "%s %s%s%s -o %s %s", compiler, testdir, PathSeparator,
cxxcmd += testdir; v.filename(), exepath, cxxflags);
cxxcmd += PathSeparator;
cxxcmd += v.filename();
cxxcmd += " -o ";
cxxcmd += exepath;
cxxcmd += " ";
cxxcmd += cxxflags;
if (!userflags.empty()) { if (!userflags.empty()) {
cxxcmd += " "; cxxcmd.get() += " ";
cxxcmd += userflags; cxxcmd.get() += userflags;
} }
int ret = system(cxxcmd.data()); int ret = system(cxxcmd.get().data());
if (ret) { if (ret) {
print_result(v.stem(), "compile errror"); print_result("compile errror");
continue; continue;
} }
ret = system(exepath.data()); ret = system(exepath.data());
if (ret) { if (ret) {
print_result(v.stem(), "runtime error"); print_result("runtime error");
continue; continue;
} }
remove(exepath.data()); remove(exepath.data());
print_result(v.stem()); print_result();
} }
writeln("\n", colors["blue"], colors["bold"], "testing done:", colors["end"]); writeln("\n", ColorBlue, ColorBold, "testing done:", ColorEnd);
writeln(colors["green"], "SUCCESS: ", nsuccess, colors["end"]); writeln(ColorGreen, "SUCCESS: ", nsuccess, ColorEnd);
writeln(colors["red"], "FAILURE: ", nfailed, colors["end"]); writeln(ColorRed, "FAILURE: ", nfailed, ColorEnd);
} }