Skip to content

Commit a2546c5

Browse files
committed
[FIX] Fixed error when the `norminette' command doens't exists. Changed file mode to append for makefile checks + Added stderr redirection. Fixed error where debug and system functions calls where being repported (like __stack_chk_fail).
Signed-off-by: Jules Lasne (seluj78) <jlasne@student.42.fr>
1 parent 7f196eb commit a2546c5

2 files changed

Lines changed: 49 additions & 35 deletions

File tree

.gitmodules

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
[submodule "libftest"]
22
path = libftest
33
url = https://github.com/jtoty/libftest
4-
[submodule "moulitest"]
5-
path = moulitest
6-
url = https://github.com/yyang42/moulitest
74
[submodule "Maintest"]
85
path = Maintest
96
url = https://github.com/QuentinPerez/Maintest
7+
[submodule "moulitest"]
8+
path = moulitest
9+
url = https://github.com/yyang42/moulitest

42PyChecker.py

Lines changed: 46 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import re
66
import shutil
77

8+
89
def check_author_file(project_path: str):
910
"""
1011
:param project_path: The path of the project where you want to check the author file
@@ -62,14 +63,17 @@ def check_norme(project_path: str):
6263
print("No source file (.c) or header (.h) to check")
6364
return 1
6465
with open(os.path.dirname(os.path.realpath(__file__)) + "/.mynorme", 'w+') as file:
65-
result = subprocess.run(['norminette'] + files.split(), stdout=subprocess.PIPE).stdout.decode('utf-8')
66-
file.write(result)
67-
error_count = result.count('Error')
68-
warning_count = result.count('Warning')
69-
if error_count != 0 and warning_count != 0:
70-
print("Found {} errors and {} warnings".format(error_count, warning_count))
71-
return 2
72-
print("Normed passed")
66+
try:
67+
result = subprocess.run(['norminette'] + files.split(), stdout=subprocess.PIPE, stderr=subprocess.STDOUT).stdout.decode('utf-8')
68+
except FileNotFoundError:
69+
file.write("Error: Norminette not found.\n")
70+
else:
71+
file.write(result)
72+
error_count = result.count('Error')
73+
warning_count = result.count('Warning')
74+
if error_count != 0 and warning_count != 0:
75+
print("Found {} errors and {} warnings".format(error_count, warning_count))
76+
return 2
7377
return 0
7478

7579

@@ -78,7 +82,7 @@ def check_makefile_clean_dir(project_path: str, binary_name: str):
7882
file.write("Cleaning Directory\n")
7983
file.write("*------------------------------------------------------*\n")
8084
file.write("")
81-
result = subprocess.run('make ' + '-C ' + project_path + ' fclean', shell=True, stdout=subprocess.PIPE).stdout.decode('utf-8')
85+
result = subprocess.run('make ' + '-C ' + project_path + ' fclean', shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT).stdout.decode('utf-8')
8286
file.write(result + '\n')
8387
if os.path.exists(project_path + '/' + binary_name):
8488
file.write("-> Error when processing rule `fclean': It should have removed {}\n".format(binary_name))
@@ -89,14 +93,14 @@ def check_makefile_clean_dir(project_path: str, binary_name: str):
8993

9094
def check_makefile_all(project_path: str, binary_name: str):
9195
makefile_path = project_path + '/Makefile'
92-
with open(os.path.dirname(os.path.realpath(__file__)) + "/.mymakefile", 'w+') as file:
96+
with open(os.path.dirname(os.path.realpath(__file__)) + "/.mymakefile", 'a') as file:
9397
file.write("*------------------------------------------------------*\n")
9498
file.write("Checking rule: `all'\n")
9599
if 'all: ' not in open(makefile_path).read():
96100
file.write("-> Error: rule `all' not found in the Makefile.\n")
97101
if 'all: $(NAME)' not in open(makefile_path).read():
98102
file.write("-> Error: rule `all' should call the rule `$(NAME)'\n")
99-
result = subprocess.run('make ' + '-C ' + project_path + ' all', shell=True, stdout=subprocess.PIPE).stdout.decode('utf-8')
103+
result = subprocess.run('make ' + '-C ' + project_path + ' all', shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT).stdout.decode('utf-8')
100104
file.write(result + '\n')
101105
if not os.path.exists(project_path + '/' + binary_name):
102106
file.write("-> Error when processing rule `fclean': It should have created {}\n".format(binary_name))
@@ -107,15 +111,15 @@ def check_makefile_all(project_path: str, binary_name: str):
107111

108112
def check_makefile_clean(project_path: str, binary_name: str):
109113
makefile_path = project_path + '/Makefile'
110-
with open(os.path.dirname(os.path.realpath(__file__)) + "/.mymakefile", 'w+') as file:
114+
with open(os.path.dirname(os.path.realpath(__file__)) + "/.mymakefile", 'a') as file:
111115
file.write("*------------------------------------------------------*\n")
112116
file.write("Checking rule: `clean'\n")
113117
if 'clean: ' not in open(makefile_path).read():
114118
file.write("-> Error: rule `clean' not found in the Makefile.\n")
115119
if not os.path.exists(project_path + '/' + binary_name):
116120
file.write("-> Error: Cannot test rule `clean' because rule `all' failed\n")
117121
# Stop the makefile test here
118-
result = subprocess.run('make ' + '-C ' + project_path + ' clean', shell=True, stdout=subprocess.PIPE).stdout.decode('utf-8')
122+
result = subprocess.run('make ' + '-C ' + project_path + ' clean', shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT).stdout.decode('utf-8')
119123
file.write(result + '\n')
120124
if not os.path.exists(project_path + '/' + binary_name):
121125
file.write("-> Error: Failing Rule: It should not have cleaned the binary named {}.".format(binary_name))
@@ -125,7 +129,7 @@ def check_makefile_clean(project_path: str, binary_name: str):
125129

126130
def check_makefile_re(project_path: str, binary_name: str):
127131
makefile_path = project_path + '/Makefile'
128-
with open(os.path.dirname(os.path.realpath(__file__)) + "/.mymakefile", 'w+') as file:
132+
with open(os.path.dirname(os.path.realpath(__file__)) + "/.mymakefile", 'a') as file:
129133
file.write("*------------------------------------------------------*\n")
130134
file.write("Checking rule: `re'\n")
131135
if 're: ' not in open(makefile_path).read():
@@ -134,7 +138,7 @@ def check_makefile_re(project_path: str, binary_name: str):
134138
file.write("-> Error: Cannot test rule `re' because rule `all' failed\n")
135139
inode1 = os.stat(project_path + '/' + binary_name).st_ino
136140
file.write("-- Before running rule `re', the {} inode is {}\n".format(binary_name, inode1))
137-
result = subprocess.run('make ' + '-C ' + project_path + ' re', shell=True, stdout=subprocess.PIPE).stdout.decode('utf-8')
141+
result = subprocess.run('make ' + '-C ' + project_path + ' re', shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT).stdout.decode('utf-8')
138142
file.write(result + '\n')
139143
inode2 = os.stat(project_path + '/' + binary_name).st_ino
140144
file.write("-- After running rule `re', the {} inode is {}\n".format(binary_name, inode2))
@@ -148,12 +152,12 @@ def check_makefile_re(project_path: str, binary_name: str):
148152

149153
def check_makefile_fclean(project_path: str, binary_name: str):
150154
makefile_path = project_path + '/Makefile'
151-
with open(os.path.dirname(os.path.realpath(__file__)) + "/.mymakefile", 'w+') as file:
155+
with open(os.path.dirname(os.path.realpath(__file__)) + "/.mymakefile", 'a') as file:
152156
file.write("*------------------------------------------------------*\n")
153157
file.write("Checking rule: `fclean'\n")
154158
if 'fclean: ' not in open(makefile_path).read():
155159
file.write("-> Error: rule `fclean' not found in the Makefile.\n")
156-
result = subprocess.run('make ' + '-C ' + project_path + ' fclean', shell=True, stdout=subprocess.PIPE).stdout.decode('utf-8')
160+
result = subprocess.run('make ' + '-C ' + project_path + ' fclean', shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT).stdout.decode('utf-8')
157161
file.write(result + '\n')
158162
if os.path.exists(project_path + '/' + binary_name):
159163
file.write("--> Error when processing rule `re': It should have removed the binary named {}\n".format(binary_name))
@@ -165,12 +169,12 @@ def check_makefile_fclean(project_path: str, binary_name: str):
165169

166170
def check_makefile_name(project_path: str, binary_name: str):
167171
makefile_path = project_path + '/Makefile'
168-
with open(os.path.dirname(os.path.realpath(__file__)) + "/.mymakefile", 'w+') as file:
172+
with open(os.path.dirname(os.path.realpath(__file__)) + "/.mymakefile", 'a') as file:
169173
file.write("*------------------------------------------------------*\n")
170174
file.write("Checking rule: `$(NAME)'\n")
171175
if '$(NAME):' not in open(makefile_path).read():
172176
file.write("-> Error: rule `$(NAME)' not found in the Makefile.\n")
173-
result = subprocess.run('make ' + '-C ' + project_path + ' ' + binary_name, shell=True, stdout=subprocess.PIPE).stdout.decode('utf-8')
177+
result = subprocess.run('make ' + '-C ' + project_path + ' ' + binary_name, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT).stdout.decode('utf-8')
174178
file.write(result + '\n')
175179
if not os.path.exists(project_path + '/' + binary_name):
176180
file.write("--> Error when processing rule `re': It should have compiled a binary named {}\n".format(binary_name))
@@ -181,14 +185,14 @@ def check_makefile_name(project_path: str, binary_name: str):
181185

182186
def check_makefile_phony(project_path: str, binary_name: str):
183187
makefile_path = project_path + '/Makefile'
184-
with open(os.path.dirname(os.path.realpath(__file__)) + "/.mymakefile", 'w+') as file:
188+
with open(os.path.dirname(os.path.realpath(__file__)) + "/.mymakefile", 'a') as file:
185189
file.write("*------------------------------------------------------*\n")
186190
file.write("Checking rule: `.PHONY'\n")
187191
if '.PHONY:' not in open(makefile_path).read():
188192
file.write("-> Error: rule `.PHONY' not found in the Makefile.\n")
189193
if not os.path.exists(project_path + '/' + binary_name):
190194
file.write("-> Error: Cannot test rule `re' because rule `$(NAME)' failed\n")
191-
result = subprocess.run('make ' + '-C ' + project_path + ' .PHONY', shell=True, stdout=subprocess.PIPE).stdout.decode('utf-8')
195+
result = subprocess.run('make ' + '-C ' + project_path + ' .PHONY', shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT).stdout.decode('utf-8')
192196
file.write(result + '\n')
193197
if not os.path.exists(project_path + '/' + binary_name):
194198
file.write("--> Error when processing rule `.PHONY': It should not have cleaned the binary named {}\n".format(binary_name))
@@ -240,16 +244,17 @@ def check_42_commandements(project_path:str):
240244

241245
def check_forbidden_functions(project_path: str, binary: str, authorized_functions):
242246
functions_called = []
243-
result = subprocess.run(['nm', project_path + '/' + binary], stdout=subprocess.PIPE).stdout.decode('utf-8')
247+
result = subprocess.run(['nm', project_path + '/' + binary], stdout=subprocess.PIPE, stderr=subprocess.STDOUT).stdout.decode('utf-8')
244248
for line in result.splitlines():
245-
if "U _" in line:
249+
if "U " in line:
246250
functions_called.append(re.sub(' +', ' ', line))
247-
sys_calls = {function.replace(' U _', '') for function in functions_called}
251+
sys_calls = {function.replace(' U ', '') for function in functions_called}
248252
sys_calls = [item for item in sys_calls if not item.startswith("ft_")]
249253
extra_function_call = [item for item in sys_calls if item not in authorized_functions]
250254
with open(os.path.dirname(os.path.realpath(__file__)) + "/.myforbiddenfunctions", 'w+') as file:
251255
for item in extra_function_call:
252-
file.write("You should justify the use of this function: `{}'\n".format(item))
256+
if not item.startswith("__"): #This is to ignore functions like `stack_chk_fail'
257+
file.write("You should justify the use of this function: `{}'\n".format(item))
253258
return 0
254259

255260

@@ -265,8 +270,14 @@ def run_libftest(project_path: str):
265270
with open('libftest/my_config.sh', 'w') as file:
266271
file.write(filedata)
267272
# @todo Parse libftest output for UI and parse score for display and return values.
268-
subprocess.run(['bash', "libftest/grademe.sh", "-s -f -n -u"])
273+
result = subprocess.run(['bash', "libftest/grademe.sh", "-l -s -f -n -u"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT).stdout.decode('utf-8')
269274
os.rename("deepthought", ".mylibftest")
275+
with open(os.path.dirname(os.path.realpath(__file__)) + "/.mylibftest", 'a') as file:
276+
file.write("\n\n\n\n\n\n\n\n\n*------------------------------------------------------*\n")
277+
file.write("LIBFTEST\n")
278+
file.write("Warning: This file contains escape sequences. Please use `cat' to view it properly.\n")
279+
file.write("*------------------------------------------------------*\n")
280+
file.write(result)
270281
return 0
271282

272283

@@ -301,12 +312,13 @@ def exec_moulitest(test_name: str):
301312
file.write("Warning: This file contains escape sequences. Please use `cat' to view it properly.\n")
302313
file.write("*------------------------------------------------------*\n")
303314
# @todo Get the result line of moulitest and parse it.
304-
result = subprocess.run('make ' + test_name + ' -C ' + 'moulitest' + ' 2>&1', shell=True, stdout=subprocess.PIPE).stdout.decode('utf-8')
315+
result = subprocess.run('make ' + test_name + ' -C ' + 'moulitest', shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT).stdout.decode('utf-8')
305316
file.write(result + '\n')
306317

307318

308319
def run_moulitest(project_path: str, has_libft_bonuses: bool, project: str):
309320
available_projects = ['ft_ls', 'ft_printf', 'gnl', 'libft', 'libftasm']
321+
# Available projects checks if the given project corresponds to one the moulitest tests.
310322
if project not in available_projects:
311323
raise ValueError("given project not in moulitest available projects.")
312324
if project == "libft":
@@ -316,10 +328,10 @@ def run_moulitest(project_path: str, has_libft_bonuses: bool, project: str):
316328
# @todo Fix moulitest makefile (it starts the bonus even when not asked.)
317329
if not has_libft_bonuses:
318330
moulitest_exclude_libft_bonuses()
319-
exec_moulitest("libft_bonus")
331+
exec_moulitest("libft_part2")
320332
moulitest_include_libft_bonuses()
321333
else:
322-
exec_moulitest("libft_bonus")
334+
exec_moulitest("libft_part2")
323335
return 0
324336

325337

@@ -356,9 +368,9 @@ def run_maintest(project_path: str):
356368
file.write("MAINTEST\n")
357369
file.write("Warning: This file contains escape sequences. Please use `cat' to view it properly.\n")
358370
file.write("*------------------------------------------------------*\n")
359-
result = subprocess.run(['gcc', 'libft_main.c', '-L' + project_path, '-I' + project_path, "-I" + project_path + "/include", "-I" + project_path + "/includes", "-lft", "-o", "libft_main.out"], stdout=subprocess.PIPE).stdout.decode('utf-8')
371+
result = subprocess.run(['gcc', 'libft_main.c', '-L' + project_path, '-I' + project_path, "-I" + project_path + "/include", "-I" + project_path + "/includes", "-lft", "-o", "libft_main.out"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT).stdout.decode('utf-8')
360372
file.write(result + '\n')
361-
result = subprocess.run(['./libft_main.out'], stdout=subprocess.PIPE).stdout.decode('utf-8')
373+
result = subprocess.run(['./libft_main.out'], stdout=subprocess.PIPE, stderr=subprocess.STDOUT).stdout.decode('utf-8')
362374
# @todo: Count number of OK and FAILs and yellow tests to get score for maintest
363375
file.write(result + '\n')
364376

@@ -411,9 +423,11 @@ def check_libft(project_path: str):
411423
check_makefile(project_path, "libft.a")
412424
check_forbidden_functions(project_path, "libft.a", authorized_functions)
413425
run_libftest(project_path)
426+
414427
run_moulitest(project_path, has_libft_bonuses, "libft")
415428
# @todo add libft-unit-test to the testing suite
416429
run_maintest(project_path)
417430
return 0
418431

419-
sys.exit(run_maintest("/tmp/libft"))
432+
433+
sys.exit(check_libft("/tmp/libft"))

0 commit comments

Comments
 (0)