Make test macros enforce unique comments

This commit is contained in:
Markus Pilman 2020-11-10 11:13:34 -07:00
parent 4c85268792
commit 16affd3575
2 changed files with 56 additions and 31 deletions

View File

@ -233,7 +233,7 @@ static double getProcessorTimeGeneric(int who) {
#endif #endif
double getProcessorTimeThread() { double getProcessorTimeThread() {
INJECT_FAULT( platform_error, "getProcessorTimeThread" ); INJECT_FAULT( platform_error, "getProcessorTimeThread" ); // Get Thread CPU Time failed
#if defined(_WIN32) #if defined(_WIN32)
FILETIME ftCreate, ftExit, ftKernel, ftUser; FILETIME ftCreate, ftExit, ftKernel, ftUser;
if (!GetThreadTimes(GetCurrentThread(), &ftCreate, &ftExit, &ftKernel, &ftUser)) { if (!GetThreadTimes(GetCurrentThread(), &ftCreate, &ftExit, &ftKernel, &ftUser)) {
@ -260,7 +260,7 @@ double getProcessorTimeThread() {
} }
double getProcessorTimeProcess() { double getProcessorTimeProcess() {
INJECT_FAULT( platform_error, "getProcessorTimeProcess" ); INJECT_FAULT( platform_error, "getProcessorTimeProcess" ); // Get CPU Process Time failed
#if defined(_WIN32) #if defined(_WIN32)
FILETIME ftCreate, ftExit, ftKernel, ftUser; FILETIME ftCreate, ftExit, ftKernel, ftUser;
if (!GetProcessTimes(GetCurrentProcess(), &ftCreate, &ftExit, &ftKernel, &ftUser)) { if (!GetProcessTimes(GetCurrentProcess(), &ftCreate, &ftExit, &ftKernel, &ftUser)) {
@ -584,7 +584,7 @@ Error systemErrorCodeToError() {
} }
void getDiskBytes(std::string const& directory, int64_t& free, int64_t& total) { void getDiskBytes(std::string const& directory, int64_t& free, int64_t& total) {
INJECT_FAULT( platform_error, "getDiskBytes" ); INJECT_FAULT( platform_error, "getDiskBytes" ); // Get disk bytes failed
#if defined(__unixish__) #if defined(__unixish__)
#if defined (__linux__) || defined (__FreeBSD__) #if defined (__linux__) || defined (__FreeBSD__)
struct statvfs buf; struct statvfs buf;
@ -634,7 +634,7 @@ void getDiskBytes(std::string const& directory, int64_t& free, int64_t& total) {
#ifdef __unixish__ #ifdef __unixish__
const char* getInterfaceName(const IPAddress& _ip) { const char* getInterfaceName(const IPAddress& _ip) {
INJECT_FAULT( platform_error, "getInterfaceName" ); INJECT_FAULT( platform_error, "getInterfaceName" ); // Get interface name failed
static char iname[20]; static char iname[20];
struct ifaddrs* interfaces = nullptr; struct ifaddrs* interfaces = nullptr;
@ -680,7 +680,7 @@ const char* getInterfaceName(const IPAddress& _ip) {
#if defined(__linux__) #if defined(__linux__)
void getNetworkTraffic(const IPAddress& ip, uint64_t& bytesSent, uint64_t& bytesReceived, uint64_t& outSegs, void getNetworkTraffic(const IPAddress& ip, uint64_t& bytesSent, uint64_t& bytesReceived, uint64_t& outSegs,
uint64_t& retransSegs) { uint64_t& retransSegs) {
INJECT_FAULT( platform_error, "getNetworkTraffic" ); // Even though this function doesn't throw errors, the equivalents for other platforms do, and since all of our simulation testing is on Linux... INJECT_FAULT( platform_error, "getNetworkTraffic" ); // getNetworkTraffic: Even though this function doesn't throw errors, the equivalents for other platforms do, and since all of our simulation testing is on Linux...
const char* ifa_name = nullptr; const char* ifa_name = nullptr;
try { try {
ifa_name = getInterfaceName(ip); ifa_name = getInterfaceName(ip);
@ -748,7 +748,7 @@ void getNetworkTraffic(const IPAddress& ip, uint64_t& bytesSent, uint64_t& bytes
} }
void getMachineLoad(uint64_t& idleTime, uint64_t& totalTime, bool logDetails) { void getMachineLoad(uint64_t& idleTime, uint64_t& totalTime, bool logDetails) {
INJECT_FAULT( platform_error, "getMachineLoad" ); // Even though this function doesn't throw errors, the equivalents for other platforms do, and since all of our simulation testing is on Linux... INJECT_FAULT( platform_error, "getMachineLoad" ); // getMachineLoad: Even though this function doesn't throw errors, the equivalents for other platforms do, and since all of our simulation testing is on Linux...
std::ifstream stat_stream("/proc/stat", std::ifstream::in); std::ifstream stat_stream("/proc/stat", std::ifstream::in);
std::string ignore; std::string ignore;
@ -765,7 +765,7 @@ void getMachineLoad(uint64_t& idleTime, uint64_t& totalTime, bool logDetails) {
} }
void getDiskStatistics(std::string const& directory, uint64_t& currentIOs, uint64_t& busyTicks, uint64_t& reads, uint64_t& writes, uint64_t& writeSectors, uint64_t& readSectors) { void getDiskStatistics(std::string const& directory, uint64_t& currentIOs, uint64_t& busyTicks, uint64_t& reads, uint64_t& writes, uint64_t& writeSectors, uint64_t& readSectors) {
INJECT_FAULT( platform_error, "getDiskStatistics" ); INJECT_FAULT( platform_error, "getDiskStatistics" ); // Getting disks statistics failed
currentIOs = 0; currentIOs = 0;
struct stat buf; struct stat buf;
@ -888,7 +888,7 @@ dev_t getDeviceId(std::string path) {
#if defined(__FreeBSD__) #if defined(__FreeBSD__)
void getNetworkTraffic(const IPAddress ip, uint64_t& bytesSent, uint64_t& bytesReceived, void getNetworkTraffic(const IPAddress ip, uint64_t& bytesSent, uint64_t& bytesReceived,
uint64_t& outSegs, uint64_t& retransSegs) { uint64_t& outSegs, uint64_t& retransSegs) {
INJECT_FAULT( platform_error, "getNetworkTraffic" ); INJECT_FAULT( platform_error, "getNetworkTraffic" ); // Get Network traffic failed
const char* ifa_name = nullptr; const char* ifa_name = nullptr;
try { try {
@ -955,7 +955,7 @@ void getNetworkTraffic(const IPAddress ip, uint64_t& bytesSent, uint64_t& bytesR
} }
void getMachineLoad(uint64_t& idleTime, uint64_t& totalTime, bool logDetails) { void getMachineLoad(uint64_t& idleTime, uint64_t& totalTime, bool logDetails) {
INJECT_FAULT( platform_error, "getMachineLoad" ); INJECT_FAULT( platform_error, "getMachineLoad" ); // Getting machine load failed
long cur[CPUSTATES], last[CPUSTATES]; long cur[CPUSTATES], last[CPUSTATES];
size_t cur_sz = sizeof cur; size_t cur_sz = sizeof cur;
@ -988,7 +988,7 @@ void getMachineLoad(uint64_t& idleTime, uint64_t& totalTime, bool logDetails) {
} }
void getDiskStatistics(std::string const& directory, uint64_t& currentIOs, uint64_t& busyTicks, uint64_t& reads, uint64_t& writes, uint64_t& writeSectors, uint64_t& readSectors) { void getDiskStatistics(std::string const& directory, uint64_t& currentIOs, uint64_t& busyTicks, uint64_t& reads, uint64_t& writes, uint64_t& writeSectors, uint64_t& readSectors) {
INJECT_FAULT( platform_error, "getDiskStatistics" ); INJECT_FAULT( platform_error, "getDiskStatistics" ); // getting disk stats failed
currentIOs = 0; currentIOs = 0;
busyTicks = 0; busyTicks = 0;
reads = 0; reads = 0;
@ -1078,7 +1078,7 @@ dev_t getDeviceId(std::string path) {
#ifdef __APPLE__ #ifdef __APPLE__
void getNetworkTraffic(const IPAddress& ip, uint64_t& bytesSent, uint64_t& bytesReceived, uint64_t& outSegs, void getNetworkTraffic(const IPAddress& ip, uint64_t& bytesSent, uint64_t& bytesReceived, uint64_t& outSegs,
uint64_t& retransSegs) { uint64_t& retransSegs) {
INJECT_FAULT( platform_error, "getNetworkTraffic" ); INJECT_FAULT( platform_error, "getNetworkTraffic" ); // Get network traffic failed (macOS)
const char* ifa_name = nullptr; const char* ifa_name = nullptr;
try { try {
@ -1141,7 +1141,7 @@ void getNetworkTraffic(const IPAddress& ip, uint64_t& bytesSent, uint64_t& bytes
} }
void getMachineLoad(uint64_t& idleTime, uint64_t& totalTime, bool logDetails) { void getMachineLoad(uint64_t& idleTime, uint64_t& totalTime, bool logDetails) {
INJECT_FAULT( platform_error, "getMachineLoad" ); INJECT_FAULT( platform_error, "getMachineLoad" ); // Getting machine load filed (macOS)
mach_msg_type_number_t count = HOST_CPU_LOAD_INFO_COUNT; mach_msg_type_number_t count = HOST_CPU_LOAD_INFO_COUNT;
host_cpu_load_info_data_t r_load; host_cpu_load_info_data_t r_load;
@ -1155,7 +1155,7 @@ void getMachineLoad(uint64_t& idleTime, uint64_t& totalTime, bool logDetails) {
} }
void getDiskStatistics(std::string const& directory, uint64_t& currentIOs, uint64_t& busyTicks, uint64_t& reads, uint64_t& writes, uint64_t& writeSectors, uint64_t& readSectors) { void getDiskStatistics(std::string const& directory, uint64_t& currentIOs, uint64_t& busyTicks, uint64_t& reads, uint64_t& writes, uint64_t& writeSectors, uint64_t& readSectors) {
INJECT_FAULT( platform_error, "getDiskStatistics" ); INJECT_FAULT( platform_error, "getDiskStatistics" ); // Getting disk stats failed (macOS)
currentIOs = 0; currentIOs = 0;
busyTicks = 0; busyTicks = 0;
writeSectors = 0; writeSectors = 0;
@ -1716,7 +1716,7 @@ void setMemoryQuota( size_t limit ) {
// ASAN doesn't work with memory quotas: https://github.com/google/sanitizers/wiki/AddressSanitizer#ulimit--v // ASAN doesn't work with memory quotas: https://github.com/google/sanitizers/wiki/AddressSanitizer#ulimit--v
return; return;
#endif #endif
INJECT_FAULT( platform_error, "setMemoryQuota" ); INJECT_FAULT( platform_error, "setMemoryQuota" ); // setting memory quota failed
#if defined(_WIN32) #if defined(_WIN32)
HANDLE job = CreateJobObject( nullptr, nullptr ); HANDLE job = CreateJobObject( nullptr, nullptr );
if (!job) { if (!job) {
@ -1920,7 +1920,7 @@ void setAffinity(int proc) {
namespace platform { namespace platform {
int getRandomSeed() { int getRandomSeed() {
INJECT_FAULT( platform_error, "getRandomSeed" ); INJECT_FAULT( platform_error, "getRandomSeed" ); // getting a random seed failed
int randomSeed; int randomSeed;
int retryCount = 0; int retryCount = 0;
@ -1963,11 +1963,11 @@ std::string joinPath( std::string const& directory, std::string const& filename
} }
void renamedFile() { void renamedFile() {
INJECT_FAULT( io_error, "renameFile" ); INJECT_FAULT( io_error, "renameFile" ); // renaming file failed
} }
void renameFile( std::string const& fromPath, std::string const& toPath ) { void renameFile( std::string const& fromPath, std::string const& toPath ) {
INJECT_FAULT( io_error, "renameFile" ); INJECT_FAULT( io_error, "renameFile" ); // rename file failed
#ifdef _WIN32 #ifdef _WIN32
if (MoveFile( fromPath.c_str(), toPath.c_str() )) { if (MoveFile( fromPath.c_str(), toPath.c_str() )) {
//renamedFile(); //renamedFile();
@ -1997,7 +1997,7 @@ void renameFile( std::string const& fromPath, std::string const& toPath ) {
void atomicReplace( std::string const& path, std::string const& content, bool textmode ) { void atomicReplace( std::string const& path, std::string const& content, bool textmode ) {
FILE* f = 0; FILE* f = 0;
try { try {
INJECT_FAULT( io_error, "atomicReplace" ); INJECT_FAULT( io_error, "atomicReplace" ); // atomic rename failed
std::string tempfilename = joinPath(parentDirectory(path), deterministicRandom()->randomUniqueID().toString() + ".tmp"); std::string tempfilename = joinPath(parentDirectory(path), deterministicRandom()->randomUniqueID().toString() + ".tmp");
f = textmode ? fopen( tempfilename.c_str(), "wt" FOPEN_CLOEXEC_MODE ) : fopen(tempfilename.c_str(), "wb"); f = textmode ? fopen( tempfilename.c_str(), "wt" FOPEN_CLOEXEC_MODE ) : fopen(tempfilename.c_str(), "wb");
@ -2081,7 +2081,7 @@ void atomicReplace( std::string const& path, std::string const& content, bool te
#error Port me! #error Port me!
#endif #endif
INJECT_FAULT( io_error, "atomicReplace" ); INJECT_FAULT( io_error, "atomicReplace" ); // io_error after atomic rename
} }
catch(Error &e) { catch(Error &e) {
TraceEvent(SevWarn, "AtomicReplace").error(e).detail("Path", path).GetLastError(); TraceEvent(SevWarn, "AtomicReplace").error(e).detail("Path", path).GetLastError();
@ -2091,12 +2091,12 @@ void atomicReplace( std::string const& path, std::string const& content, bool te
} }
static bool deletedFile() { static bool deletedFile() {
INJECT_FAULT( platform_error, "deleteFile" ); INJECT_FAULT( platform_error, "deleteFile" ); // delete file failed
return true; return true;
} }
bool deleteFile( std::string const& filename ) { bool deleteFile( std::string const& filename ) {
INJECT_FAULT( platform_error, "deleteFile" ); INJECT_FAULT( platform_error, "deleteFile" ); // file deletion failed
#ifdef _WIN32 #ifdef _WIN32
if (DeleteFile(filename.c_str())) if (DeleteFile(filename.c_str()))
return deletedFile(); return deletedFile();
@ -2115,12 +2115,14 @@ bool deleteFile( std::string const& filename ) {
throw e; throw e;
} }
static void createdDirectory() { INJECT_FAULT( platform_error, "createDirectory" ); } static void createdDirectory() {
INJECT_FAULT( platform_error, "createDirectory" ); // create dir (noargs) failed
}
namespace platform { namespace platform {
bool createDirectory( std::string const& directory ) { bool createDirectory( std::string const& directory ) {
INJECT_FAULT( platform_error, "createDirectory" ); INJECT_FAULT( platform_error, "createDirectory" ); // create dir failed
#ifdef _WIN32 #ifdef _WIN32
if (CreateDirectory( directory.c_str(), nullptr )) { if (CreateDirectory( directory.c_str(), nullptr )) {
@ -2261,7 +2263,7 @@ std::string abspath( std::string const& path, bool resolveLinks, bool mustExist
} }
// Returns an absolute path canonicalized to use only CANONICAL_PATH_SEPARATOR // Returns an absolute path canonicalized to use only CANONICAL_PATH_SEPARATOR
INJECT_FAULT( platform_error, "abspath" ); INJECT_FAULT( platform_error, "abspath" ); // abspath failed
if(!resolveLinks) { if(!resolveLinks) {
// TODO: Not resolving symbolic links does not yet behave well on Windows because of drive letters // TODO: Not resolving symbolic links does not yet behave well on Windows because of drive letters
@ -2367,7 +2369,7 @@ bool acceptDirectory( FILE_ATTRIBUTE_DATA fileAttributes, std::string const& nam
ACTOR Future<vector<std::string>> findFiles( std::string directory, std::string extension, ACTOR Future<vector<std::string>> findFiles( std::string directory, std::string extension,
bool directoryOnly, bool async) { bool directoryOnly, bool async) {
INJECT_FAULT( platform_error, "findFiles" ); INJECT_FAULT( platform_error, "findFiles" ); // findFiles failed (Win32)
state vector<std::string> result; state vector<std::string> result;
state int64_t tsc_begin = __rdtsc(); state int64_t tsc_begin = __rdtsc();
@ -2417,7 +2419,7 @@ bool acceptDirectory( FILE_ATTRIBUTE_DATA fileAttributes, std::string const& nam
ACTOR Future<vector<std::string>> findFiles( std::string directory, std::string extension, ACTOR Future<vector<std::string>> findFiles( std::string directory, std::string extension,
bool directoryOnly, bool async) { bool directoryOnly, bool async) {
INJECT_FAULT( platform_error, "findFiles" ); INJECT_FAULT( platform_error, "findFiles" ); // findFiles failed
state vector<std::string> result; state vector<std::string> result;
state int64_t tsc_begin = __rdtsc(); state int64_t tsc_begin = __rdtsc();

View File

@ -36,6 +36,9 @@ namespace coveragetool
public string Condition; public string Condition;
}; };
class ParseException : Exception {
}
class Program class Program
{ {
public static int Main(string[] args) public static int Main(string[] args)
@ -82,10 +85,14 @@ namespace coveragetool
.Where( fi=>new FileInfo(fi).LastWriteTimeUtc > outputTime ) .Where( fi=>new FileInfo(fi).LastWriteTimeUtc > outputTime )
.ToLookup(n=>n); .ToLookup(n=>n);
cases = cases try {
cases = cases
.Where(c => exists.Contains(c.File) && !changedFiles.Contains(c.File)) .Where(c => exists.Contains(c.File) && !changedFiles.Contains(c.File))
.Concat( changedFiles.SelectMany( f => ParseSource( f.Key ) ) ) .Concat( changedFiles.SelectMany( f => ParseSource( f.Key ) ) )
.ToArray(); .ToArray();
} catch (ParseException) {
return 1;
}
if (!quiet) { if (!quiet) {
Console.WriteLine(" {0}/{1} files scanned", changedFiles.Count, inputPaths.Length); Console.WriteLine(" {0}/{1} files scanned", changedFiles.Count, inputPaths.Length);
@ -140,10 +147,10 @@ namespace coveragetool
} }
public static CoverageCase[] ParseSource(string filename) public static CoverageCase[] ParseSource(string filename)
{ {
var regex = new Regex( @"^([^/]|/[^/])*(TEST|INJECT_FAULT|SHOULD_INJECT_FAULT)[ \t]*\(([^)]*)\)" ); var regex = new Regex( @"^([^/]|/[^/])*\s+(TEST|INJECT_FAULT|SHOULD_INJECT_FAULT)[ \t]*\(([^)]*)\)" );
var lines = File.ReadAllLines(filename); var lines = File.ReadAllLines(filename);
return Enumerable.Range(0, lines.Length) var res = Enumerable.Range(0, lines.Length)
.Where( i=>regex.IsMatch(lines[i]) && !lines[i].StartsWith("#define") ) .Where( i=>regex.IsMatch(lines[i]) && !lines[i].StartsWith("#define") )
.Select( i=>new CoverageCase { .Select( i=>new CoverageCase {
File = filename, File = filename,
@ -152,6 +159,22 @@ namespace coveragetool
Condition = regex.Match(lines[i]).Groups[3].Value Condition = regex.Match(lines[i]).Groups[3].Value
} ) } )
.ToArray(); .ToArray();
var comments = new Dictionary<string, CoverageCase>();
bool isUnique = true;
foreach(var coverageCase in res) {
if (comments.ContainsKey(coverageCase.Comment)) {
isUnique = false;
var prev = comments[coverageCase.Comment];
Console.Error.WriteLine(String.Format("Error at {0}:{1}: {2} is not a unique comment", coverageCase.File, coverageCase.Line, coverageCase.Comment));
Console.Error.WriteLine(String.Format("\tPreviously seen in {0} at {1}", prev.File, prev.Line));
} else {
comments.Add(coverageCase.Comment, coverageCase);
}
}
if (!isUnique) {
throw new ParseException();
}
return res;
} }
public static string FindComment(string line) public static string FindComment(string line)
{ {