Skip to content

Commit e688cf2

Browse files
Tal500Tal Hadad
authored andcommitted
fixes, safe asserts, and more tests
1 parent 4d4bab8 commit e688cf2

2 files changed

Lines changed: 77 additions & 34 deletions

File tree

integration_test.py

Lines changed: 50 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -51,10 +51,11 @@ def test_relative_header_1(record_property, tmpdir, with_pragma_once, is_sys):
5151
else:
5252
assert double_include_error in stderr
5353

54+
@pytest.mark.parametrize("with_pragma_once", (False, True))
5455
@pytest.mark.parametrize("inv", (False, True))
5556
@pytest.mark.parametrize("source_relative", (False, True))
56-
def test_relative_header_2(record_property, tmpdir, inv, source_relative):
57-
header_file, _ = __test_relative_header_create_header(tmpdir)
57+
def test_relative_header_2(record_property, tmpdir, with_pragma_once, inv, source_relative):
58+
header_file, double_include_error = __test_relative_header_create_header(tmpdir, with_pragma_once=with_pragma_once)
5859

5960
test_file = __test_relative_header_create_source(tmpdir, "test.h", header_file, inv=inv)
6061

@@ -63,11 +64,14 @@ def test_relative_header_2(record_property, tmpdir, inv, source_relative):
6364
_, stdout, stderr = simplecpp(args, cwd=tmpdir)
6465
record_property("stdout", stdout)
6566
record_property("stderr", stderr)
66-
assert stderr == ''
67-
if source_relative and not inv:
68-
assert '#line 8 "test.h"' in stdout
67+
if with_pragma_once:
68+
assert stderr == ''
69+
if inv:
70+
assert f'#line 8 "{pathlib.PurePath(tmpdir).as_posix()}/test.h"' in stdout
71+
else:
72+
assert '#line 8 "test.h"' in stdout
6973
else:
70-
assert f'#line 8 "{pathlib.PurePath(tmpdir).as_posix()}/test.h"' in stdout
74+
assert double_include_error in stderr
7175

7276
@pytest.mark.parametrize("is_sys", (False, True))
7377
@pytest.mark.parametrize("inv", (False, True))
@@ -89,15 +93,16 @@ def test_relative_header_3(record_property, tmpdir, is_sys, inv, source_relative
8993
assert "missing header: Header not found" in stderr
9094
else:
9195
assert stderr == ''
92-
if source_relative and not inv:
93-
assert '#line 8 "test_subdir/test.h"' in stdout
94-
else:
96+
if inv:
9597
assert f'#line 8 "{pathlib.PurePath(test_subdir).as_posix()}/test.h"' in stdout
98+
else:
99+
assert '#line 8 "test_subdir/test.h"' in stdout
96100

97101
@pytest.mark.parametrize("use_short_path", (False, True))
102+
@pytest.mark.parametrize("relative_include_dir", (False, True))
98103
@pytest.mark.parametrize("is_sys", (False, True))
99104
@pytest.mark.parametrize("inv", (False, True))
100-
def test_relative_header_4(record_property, tmpdir, use_short_path, is_sys, inv):
105+
def test_relative_header_4(record_property, tmpdir, use_short_path, relative_include_dir, is_sys, inv):
101106
test_subdir = os.path.join(tmpdir, "test_subdir")
102107
os.mkdir(test_subdir)
103108
header_file, _ = __test_relative_header_create_header(test_subdir)
@@ -106,17 +111,22 @@ def test_relative_header_4(record_property, tmpdir, use_short_path, is_sys, inv)
106111

107112
test_file = __test_relative_header_create_source(tmpdir, header_file, "test.h", is_include2_sys=is_sys, inv=inv)
108113

109-
args = [format_include_path_arg(test_subdir), test_file]
114+
args = [format_include_path_arg("test_subdir" if relative_include_dir else test_subdir), test_file]
110115

111116
_, stdout, stderr = simplecpp(args, cwd=tmpdir)
112117
record_property("stdout", stdout)
113118
record_property("stderr", stderr)
114119
assert stderr == ''
120+
if (use_short_path and not inv) or (relative_include_dir and inv):
121+
assert '#line 8 "test_subdir/test.h"' in stdout
122+
else:
123+
assert f'#line 8 "{pathlib.PurePath(test_subdir).as_posix()}/test.h"' in stdout
115124

116125
@pytest.mark.parametrize("with_pragma_once", (False, True))
126+
@pytest.mark.parametrize("relative_include_dir", (False, True))
117127
@pytest.mark.parametrize("is_sys", (False, True))
118128
@pytest.mark.parametrize("inv", (False, True))
119-
def test_relative_header_5(record_property, tmpdir, with_pragma_once, is_sys, inv): # test relative paths with ..
129+
def test_relative_header_5(record_property, tmpdir, with_pragma_once, relative_include_dir, is_sys, inv): # test relative paths with ..
120130
## in this test, the subdir role is the opposite then the previous - it contains the test.c file, while the parent tmpdir contains the header file
121131
header_file, double_include_error = __test_relative_header_create_header(tmpdir, with_pragma_once=with_pragma_once)
122132
if is_sys:
@@ -128,16 +138,42 @@ def test_relative_header_5(record_property, tmpdir, with_pragma_once, is_sys, in
128138
os.mkdir(test_subdir)
129139
test_file = __test_relative_header_create_source(test_subdir, header_file, header_file_second_path, is_include2_sys=is_sys, inv=inv)
130140

131-
args = ([format_include_path_arg(tmpdir)] if is_sys else []) + ["test.c"]
141+
args = ([format_include_path_arg(".." if relative_include_dir else tmpdir)] if is_sys else []) + ["test.c"]
132142

133143
_, stdout, stderr = simplecpp(args, cwd=test_subdir)
134144
record_property("stdout", stdout)
135145
record_property("stderr", stderr)
136146
if with_pragma_once:
137147
assert stderr == ''
138-
if inv:
148+
if (relative_include_dir or not is_sys) and inv:
139149
assert '#line 8 "../test.h"' in stdout
140150
else:
141151
assert f'#line 8 "{pathlib.PurePath(tmpdir).as_posix()}/test.h"' in stdout
142152
else:
143153
assert double_include_error in stderr
154+
155+
@pytest.mark.parametrize("with_pragma_once", (False, True))
156+
@pytest.mark.parametrize("relative_include_dir", (False, True))
157+
@pytest.mark.parametrize("is_sys", (False, True))
158+
@pytest.mark.parametrize("inv", (False, True))
159+
def test_relative_header_6(record_property, tmpdir, with_pragma_once, relative_include_dir, is_sys, inv): # test relative paths with .. that is resolved only by an include dir
160+
## in this test, both the header and the source file are at the same dir, but there is a dummy inclusion dir as a subdir
161+
header_file, double_include_error = __test_relative_header_create_header(tmpdir, with_pragma_once=with_pragma_once)
162+
163+
test_subdir = os.path.join(tmpdir, "test_subdir")
164+
os.mkdir(test_subdir)
165+
test_file = __test_relative_header_create_source(tmpdir, header_file, "../test.h", is_include2_sys=is_sys, inv=inv)
166+
167+
args = [format_include_path_arg("test_subdir" if relative_include_dir else test_subdir), "test.c"]
168+
169+
_, stdout, stderr = simplecpp(args, cwd=tmpdir)
170+
record_property("stdout", stdout)
171+
record_property("stderr", stderr)
172+
if with_pragma_once:
173+
assert stderr == ''
174+
if relative_include_dir and inv:
175+
assert '#line 8 "test.h"' in stdout
176+
else:
177+
assert f'#line 8 "{pathlib.PurePath(tmpdir).as_posix()}/test.h"' in stdout
178+
else:
179+
assert double_include_error in stderr

simplecpp.cpp

Lines changed: 27 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -2719,9 +2719,7 @@ static std::string toAbsolutePath(const std::string& path) {
27192719
return simplecpp::simplifyPath(path);
27202720
}
27212721

2722-
// templated function for compiler optimization opportunities
2723-
template <bool withTrailingSlash>
2724-
static std::string dirPath(const std::string& path) {
2722+
static std::string dirPath(const std::string& path, bool withTrailingSlash=true) {
27252723
const std::size_t firstSlash = path.find_last_of("\\/");
27262724
if (firstSlash == std::string::npos) {
27272725
return "";
@@ -2742,7 +2740,7 @@ static std::string extractRelativePathFromAbsolute(const std::string& absoluteSi
27422740
std::string leadingParenting;
27432741
while (!startsWith_(normalizedAbsolutePath, currentPrefix)) {
27442742
leadingParenting = "../" + leadingParenting;
2745-
currentPrefix = dirPath<false>(currentPrefix);
2743+
currentPrefix = dirPath(currentPrefix, false);
27462744
}
27472745
const std::size_t size = currentPrefix.size();
27482746
std::string relativeFromMeetingPath = normalizedAbsolutePath.substr(size, normalizedAbsolutePath.size() - size);
@@ -3169,26 +3167,24 @@ static std::string openHeader(std::ifstream &f, const std::string &path)
31693167
return "";
31703168
}
31713169

3172-
// templated function for compiler optimization opportunities
3173-
template <bool expandBaseWithAbsolutePath, bool exactRelative>
31743170
static std::string getRelativeFileName(const std::string &baseFile, const std::string &header)
31753171
{
31763172
const std::string baseFileSimplified = simplecpp::simplifyPath(baseFile);
3177-
const std::string baseFileNormalized = (expandBaseWithAbsolutePath && !isAbsolutePath(baseFileSimplified)) ? (currentDirectory() + "/" + baseFileSimplified) : baseFileSimplified;
3173+
const std::string baseFileAbsolute = isAbsolutePath(baseFileSimplified) ?
3174+
baseFileSimplified :
3175+
simplecpp::simplifyPath(currentDirectory() + "/" + baseFileSimplified);
31783176

31793177
const std::string headerSimplified = simplecpp::simplifyPath(header);
3180-
const std::string path = isAbsolutePath(headerSimplified) ? headerSimplified : (dirPath<true>(baseFileNormalized) + headerSimplified);
3181-
if (exactRelative) {
3182-
const std::string absolutePath = expandBaseWithAbsolutePath ? path : toAbsolutePath(path);
3183-
const std::string absoluteBaseFile = expandBaseWithAbsolutePath ? baseFileNormalized : toAbsolutePath(baseFileNormalized);
3184-
return extractRelativePathFromAbsolute(absolutePath, dirPath<true>(absoluteBaseFile));
3185-
}
3186-
return path;
3178+
const std::string path = isAbsolutePath(headerSimplified) ?
3179+
headerSimplified :
3180+
simplecpp::simplifyPath(dirPath(baseFileAbsolute) + headerSimplified);
3181+
3182+
return extractRelativePathFromAbsolute(path);
31873183
}
31883184

31893185
static std::string openHeaderRelative(std::ifstream &f, const std::string &sourcefile, const std::string &header)
31903186
{
3191-
return openHeader(f, getRelativeFileName<false, false>(sourcefile, header));
3187+
return openHeader(f, getRelativeFileName(sourcefile, header));
31923188
}
31933189

31943190
// returns the simplified header path:
@@ -3205,8 +3201,9 @@ static std::string getIncludePathFileName(const std::string &includePath, const
32053201
std::string basePath = toAbsolutePath(includePath);
32063202
if (!basePath.empty() && basePath[basePath.size()-1U]!='/' && basePath[basePath.size()-1U]!='\\')
32073203
basePath += '/';
3208-
const std::string absoluteSimplifiedHeaderPath = basePath + simplifiedHeader;
3209-
return extractRelativePathFromAbsolute(absoluteSimplifiedHeaderPath);
3204+
const std::string absoluteSimplifiedHeaderPath = simplecpp::simplifyPath(basePath + simplifiedHeader);
3205+
// preserve absoluteness/relativieness of the including dir
3206+
return isAbsolutePath(includePath) ? absoluteSimplifiedHeaderPath : extractRelativePathFromAbsolute(absoluteSimplifiedHeaderPath);
32103207
}
32113208

32123209
static std::string openHeaderIncludePath(std::ifstream &f, const simplecpp::DUI &dui, const std::string &header)
@@ -3270,7 +3267,7 @@ static std::string getFileIdPath(const std::map<std::string, simplecpp::TokenLis
32703267
}
32713268

32723269
if (!systemheader) {
3273-
const std::string relativeOrAbsoluteFilename = getRelativeFileName<true, true>(sourcefile, header);// unknown if absolute or relative, but always simplified
3270+
const std::string relativeOrAbsoluteFilename = getRelativeFileName(sourcefile, header);// unknown if absolute or relative, but always simplified
32743271
const std::string match = findPathInMapBothRelativeAndAbsolute(filedata, relativeOrAbsoluteFilename);
32753272
if (!match.empty()) {
32763273
return match;
@@ -3294,6 +3291,16 @@ static bool hasFile(const std::map<std::string, simplecpp::TokenList *> &filedat
32943291
return !getFileIdPath(filedata, sourcefile, header, dui, systemheader).empty();
32953292
}
32963293

3294+
static void safeInsertTokenListToMap(std::map<std::string, simplecpp::TokenList *> &filedata, const std::string &header2, simplecpp::TokenList *tokens, const std::string &header, const std::string &sourcefile, bool systemheader, const char* contextDesc)
3295+
{
3296+
const bool inserted = filedata.insert(std::make_pair(header2, tokens)).second;
3297+
if (!inserted) {
3298+
std::cerr << "error in " << contextDesc << " - attempt to add a tokenized file to the file map, but this file is already in the map! Details:" <<
3299+
"header: " << header << " header2: " << header2 << " source: " << sourcefile << " systemheader: " << systemheader << std::endl;
3300+
abort();
3301+
}
3302+
}
3303+
32973304
std::map<std::string, simplecpp::TokenList*> simplecpp::load(const simplecpp::TokenList &rawtokens, std::vector<std::string> &filenames, const simplecpp::DUI &dui, simplecpp::OutputList *outputList)
32983305
{
32993306
#ifdef SIMPLECPP_WINDOWS
@@ -3370,7 +3377,7 @@ std::map<std::string, simplecpp::TokenList*> simplecpp::load(const simplecpp::To
33703377
TokenList *tokens = new TokenList(header2, filenames, outputList);
33713378
if (dui.removeComments)
33723379
tokens->removeComments();
3373-
ret[header2] = tokens;
3380+
safeInsertTokenListToMap(ret, header2, tokens, header, rawtok->location.file(), systemheader, "simplecpp::load");
33743381
if (tokens->front())
33753382
filelist.push_back(tokens->front());
33763383
}
@@ -3657,7 +3664,7 @@ void simplecpp::preprocess(simplecpp::TokenList &output, const simplecpp::TokenL
36573664
TokenList * const tokens = new TokenList(header2, files, outputList);
36583665
if (dui.removeComments)
36593666
tokens->removeComments();
3660-
filedata[header2] = tokens;
3667+
safeInsertTokenListToMap(filedata, header2, tokens, header, rawtok->location.file(), systemheader, "simplecpp::preprocess");
36613668
}
36623669
}
36633670
if (header2.empty()) {

0 commit comments

Comments
 (0)