Files
lmms/tests/scripted/verify
Rossmaxx 68ea3f5bf2 Remove debian folder (#7311)
* removed debian folder

* removed debian entries from check-strings

* fixup verify script too
2024-06-15 08:29:14 +05:30

232 lines
7.4 KiB
Python
Executable File

#!/usr/bin/python3
import subprocess
from pathlib import Path
import tempfile
import os
import sys
def set_git_config():
"""Set local git identity, but only in local repo (to not overwrite user settings)"""
"""Also, fix git issue: fatal: transport 'file' not allowed"""
subprocess.run(['git', 'config', 'user.name', 'James Bond'])
subprocess.run(['git', 'config', 'user.email', '007@sis.gov.uk'])
subprocess.run(['git', 'config', '--global', 'protocol.file.allow', 'always'])
def create_file(filename: str, file_content: str):
"""Create a file in the current directory and adds it to git"""
Path(filename).parent.mkdir(parents=True, exist_ok=True)
with open(filename, "w", encoding='utf-8') as textfile:
print(file_content, file=textfile)
subprocess.run(['git', 'add', filename], check=True)
class ScriptTest():
def __init__(self, scriptpath: Path):
self.scriptpath = Path(scriptpath)
def __enter__(self):
"""Create temporary, minimal test environment, and change to it"""
self.lmms_tmpdir = tempfile.TemporaryDirectory(dir='.')
os.chdir(self.lmms_tmpdir.name)
# prerequirements
Path('data/themes').mkdir(parents=True)
subprocess.run(['git', 'init', '-b', 'main'], check=True)
set_git_config()
subprocess.run(['git', 'submodule', 'add', '../../carla', 'plugins/CarlaBase/carla'], check=True)
create_file('src/core/classes.cpp', 'namespace lmms {\nclass TestClass\n}')
create_file('data/locale/de.ts',
'<?xml version="1.0" ?><!DOCTYPE TS><TS language="de" version="2.1">\n'
' <context>\n'
' <name>TestClass</name>\n'
' <message>\n'
' <location filename="../../src/core/classes.cpp" line="20"/>\n'
' <source>About LMMS</source>\n'
' <translation>Über LMMS</translation>\n'
' </message>\n'
'</context>\n'
'</TS>\n')
subprocess.run(['git', 'commit', '-m', 'Initial commit'], check=True)
return self
def __exit__(self, type, value, traceback):
"""Leave and destroy temporary test environment"""
os.chdir('..')
self.lmms_tmpdir.cleanup()
def expect(self, expectation: str):
"""Check if "expectation" is in the output"""
if expectation not in self.result.stdout:
raise RuntimeError(f'Expected "{expectation}" in script output')
def run(self, expected_returncode: int = 1): # default: something goes wrong ("to the safe side")
"""Run the script, check the exit code and store the result"""
command = [str(self.scriptpath)]
if os.name == 'nt':
command.insert(0, sys.executable)
self.result = subprocess.run(command, capture_output=True, text=True)
print('--->8--- Script output BEGIN --->8---')
print(self.result.stdout)
print('--->8--- Script output END --->8---')
if self.result.stderr:
print('--->8--- Script error output BEGIN --->8---')
print(self.result.stderr)
print('--->8--- Script error output END --->8---')
# make sure script returned "error" (because we test for errors) and that the output is as expected
if self.result.returncode != expected_returncode:
raise RuntimeError(f"Script \"check-strings\" returned {self.result.returncode}, "
f"but {expected_returncode} expected")
lmms_main_path = Path(__file__).resolve().parent.parent.parent
with tempfile.TemporaryDirectory() as tmpdir:
os.chdir(tmpdir)
check_strings = lmms_main_path / 'tests' / 'scripted' / 'check-strings'
check_namespace = lmms_main_path / 'tests' / 'scripted' / 'check-namespace'
# create dummy carla repo
Path('carla').mkdir()
os.chdir('carla')
subprocess.run(['git', 'init', '-b', 'main'], check=True)
set_git_config()
create_file('README.md', 'hello world')
subprocess.run(['git', 'commit', '-m', 'Initial commit'], check=True)
os.chdir('..')
Path('lmms').mkdir()
os.chdir('lmms')
# minimal working example
with ScriptTest(check_strings) as test:
test.run(0) # exitcode 0 - no errors expected
test.expect('0 errors')
with ScriptTest(check_strings) as test:
create_file('data/locale/fr.ts',
'<?xml version="1.0" ?><!DOCTYPE TS><TS language="de" version="2.1">\n'
' <context>\n'
' <name>NonExistentClass</name>\n'
' <message>\n'
' <location filename="../../src/core/classes.cpp" line="20"/>\n'
' <source>About LMMS</source>\n'
' <translation>À propos de LMMS</translation>\n'
' </message>\n'
'</context>\n'
'</TS>\n')
test.run()
test.expect('Error: data/locale: Class does not exist in source code: NonExistentClass')
test.expect('1 errors')
with ScriptTest(check_strings) as test:
create_file('data/themes/classic/style.css',
'lmms--gui--NonExistentClass {'
'\tcolor: #d1d8e4;\n'
'}')
test.run()
test.expect('Error: data/themes/classic/style.css: Class does not exist in source code: NonExistentClass')
test.expect('1 errors')
with ScriptTest(check_namespace) as test:
# minimal working example
test.run(0) # exitcode 0 - no errors expected
test.expect('0 errors')
create_file('01_OddBraceWithinMacro.cpp', '''
#if HAS_EVEN_BRACES
namespace lmms {}
#endif
namespace lmms {
#if HAS_ODD_BRACE
}
#endif
''')
create_file('02_IncludeInCodeBlock.cpp', '''
#include <good>
extern "C" {
#include "alright.c"
}
namespace lmms {
#include <bad>
}
''')
create_file('03_MacroComments.h', '''
#ifndef HEADER_GUARD_NEEDS_NO_COMMENT
#define HEADER_GUARD_NEEDS_NO_COMMENT
#ifdef HAS_NESTED_NEEDS_COMMENT
#ifdef SHORT_NO_NESTED_NEEDS_NO_COMMENT
namespace lmms {}
#endif
#endif
#ifdef HAS_COMMENT
#ifdef SHORT_NO_NESTED_NEEDS_NO_COMMENT
#else
#endif
#endif // HAS_COMMENT
#endif
''')
create_file('04_NamespaceComments.cpp', '''
namespace lmms {
namespace ShortNamespace {
class WithDeclarationsOnly;
}
namespace LongNamespace {
class WithDefinition {
int x;
};
}
} // namespace lmms
''')
create_file('05_NoHeaderGuard.h', '''
#include <cstdio>
namespace lmms {}
''')
create_file('06_PragmaButNoLmms.h', '''
// should not cause header guard warning
#pragma once
namespace not_lmms {}
''')
create_file('07_MismatchingEndifName.h', '''
#ifndef ABC_H
namespace lmms {
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
}
#endif // XYZ_H
''')
create_file('08_MismatchingNamespaceEndName.h', '''
#ifndef ABC_H
namespace lmms {
{}
} // namespace smml
#endif // ABC_H
''')
create_file('09_NoEndifAfterElseIsOk.cpp', '''
#ifdef XYZ
namespace lmms {
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
}
#else
namespace lmms {
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
}
#endif
''')
test.run()
test.expect('8 errors')
test.expect('''
Error: 01_OddBraceWithinMacro.cpp:7: Expected #endif before }
Error: 02_IncludeInCodeBlock.cpp:7: #include inside a code block
Error: 03_MacroComments.h:8: Missing comment // HAS_NESTED_NEEDS_COMMENT
Error: 04_NamespaceComments.cpp:10: Missing comment // namespace LongNamespace
Error: 05_NoHeaderGuard.h: First statement should be header guard
Error: 06_PragmaButNoLmms.h: File has no namespace lmms
Error: 07_MismatchingEndifName.h:36: Missing comment // ABC_H
Error: 08_MismatchingNamespaceEndName.h:5: Missing comment // namespace lmms
''')
# if we made it until here without an exception, all tests have been passed
print("SUCCESS")