Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Build tests on all platforms and run them on Linux/Mac platforms #126

Merged
merged 4 commits into from
Jul 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 29 additions & 2 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ jobs:
run: |
python3 run_tests.py


build-macos:
runs-on: macos-14
steps:
Expand All @@ -48,13 +49,27 @@ jobs:
git clone https://github.com/microsoft/vcpkg.git
./vcpkg/bootstrap-vcpkg.sh

- name: Download Unit Test Designs
run: |
python -m pip install -r test/py/requirements.txt
python test/py/testing.py --download_repos true --database_file_path repos.yaml --third_party_path test/designs

- name: Create Unit Tests
run: |
python test/py/testing.py --generate_unit_tests true --database_file_path repos.yaml --unit_test_path test/src/generated_tests --third_party_path test/designs


- name: Build Library and CLI Application
run: |
export VCPKG_ROOT=$(realpath ./vcpkg)
export CMAKE_BUILD_PARALLEL_LEVEL=2
cmake --preset release -DENABLE_UNIT_TESTING=OFF
cmake --preset release -DENABLE_UNIT_TESTING=ON
cmake --build --preset release

- name: Run Tests
run: |
python3 run_tests.py


build-windows:
runs-on: windows-2022
Expand All @@ -65,10 +80,22 @@ jobs:
git clone https://github.com/microsoft/vcpkg.git
.\vcpkg\bootstrap-vcpkg.bat

- name: Download Unit Test Designs
run: |
${ENV:PYTHONUTF8}=1
git config --system core.longpaths true
python -m pip install -r test/py/requirements.txt
python test/py/testing.py --download_repos true --database_file_path repos.yaml --third_party_path test\designs

- name: Create Unit Tests
run: |
${ENV:PYTHONUTF8}=1
git config --system core.longpaths true
python test/py/testing.py --generate_unit_tests true --database_file_path repos.yaml --unit_test_path test\src\generated_tests --third_party_path test\designs

- name: Build Library and CLI Application
run: |
${ENV:VCPKG_ROOT}=$(Resolve-Path ./vcpkg)
${ENV:CMAKE_BUILD_PARALLEL_LEVEL}=2
cmake --preset release -DENABLE_UNIT_TESTING=OFF
cmake --preset release -DENABLE_UNIT_TESTING=ON
cmake --build --preset release
5 changes: 5 additions & 0 deletions lib/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,11 @@ set(SOURCES
# Create library file from sources
add_library(${NAME_LIB} SHARED ${SOURCES})

# Disable warnings
# warning C4996: 'x': This function or variable may be unsafe. Consider using x instead.
# To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
target_compile_options(${NAME_LIB} PRIVATE $<$<COMPILE_LANG_AND_ID:CXX,MSVC>:/wd4996>)

target_include_directories(${NAME_LIB} PRIVATE
${COMPOUNDFILEREADER_INCLUDE_DIRS}
${LIB_INCLUDE_DIR}
Expand Down
16 changes: 12 additions & 4 deletions run_tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,11 @@


class TestThread(threading.Thread):
def __init__(self, shard_count: int, shard_index: int):
def __init__(self, test_file: Path, shard_count: int, shard_index: int):
threading.Thread.__init__(self)
self.shard_count = shard_count
self.shard_index = shard_index
self.test_file = test_file

def run(self):
global tests_ran_successfully
Expand All @@ -48,9 +49,16 @@ def run(self):
print(f"Starting shard {self.shard_index + 1} / {self.shard_count}")
lock.release()

cmd = [
str(self.test_file),
"--shard-count",
str(self.shard_count),
"--shard-index",
str(self.shard_index),
]

result = subprocess.run(
f"{test_file} --shard-count {self.shard_count} --shard-index {self.shard_index}",
shell=True,
cmd,
capture_output=True,
text=True,
)
Expand Down Expand Up @@ -79,7 +87,7 @@ def run(self):

TEST_SHARDS = 8
for idx in range(TEST_SHARDS):
threads += [TestThread(TEST_SHARDS, idx)]
threads += [TestThread(test_file, TEST_SHARDS, idx)]

start_time = datetime.now()

Expand Down
5 changes: 5 additions & 0 deletions test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,11 @@ set(HEADERS
# Create executable file from sources
add_executable(${NAME_TEST} ${SOURCES} ${HEADERS})

# Disable warnings
# warning C4996: 'x': This function or variable may be unsafe. Consider using x instead.
# To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
target_compile_options(${NAME_TEST} PRIVATE $<$<COMPILE_LANG_AND_ID:CXX,MSVC>:/wd4996>)

target_include_directories(${NAME_TEST} PRIVATE
${LIB_INCLUDE_DIR}
${TEST_INCLUDE_DIR}
Expand Down
4 changes: 2 additions & 2 deletions test/py/FileErrorDatabase.py
Original file line number Diff line number Diff line change
Expand Up @@ -114,8 +114,8 @@ def cloneRepoTo(self, repo: Repository, base_path: str) -> None:

try:
fs_repo = Repo.clone_from(repo.url, export_dir)
except:
raise Exception(f'Failed cloning repository from `{repo.url}`!')
except Exception as ex:
raise Exception(f'Failed cloning repository from `{repo.url}`!\n{ex}')

# Commit differs from currently downloaded master
if str(fs_repo.head.commit) != repo.commit:
Expand Down
5 changes: 3 additions & 2 deletions test/py/requirements.txt
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
GitPython==3.1.26
pydantic==1.9.0
GitPython==3.1.43
pydantic==1.9.0
pyyaml==6.0.1
55 changes: 28 additions & 27 deletions test/py/testing.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,45 +10,46 @@

from FileErrorDatabase import RepoFile, Repository, FileErrorDatabase

import logging

logging.basicConfig(level=logging.DEBUG)

ExtensionsOfInterest = ['*.OBK', '*.OLB', '*.DSN', '*.DBK']

def get_files_of_interest(path: str, file_extensions: List[str]) -> List[str]:
def get_files_of_interest(path: Path, file_extensions: List[str]) -> List[Path]:
"""
Get a list of absolute paths to files with specified extension.
This function searches recursively through the path.

Usage e.g.
>>> files = get_files_of_interest('/home/some_dir', ['*.txt', '*.log'])
>>> files = get_files_of_interest(Path('/home/some_dir'), ['*.txt', '*.log'])
>>> print(files)
>>> ['/home/som_dir/sub_dir/foo.txt', '/home/some_dir/bar.log']
"""

files = []

for extension in file_extensions:
for file in Path(path).rglob(extension):
for file in path.rglob(extension):
files += [file]

return files

def add_new_repo_to_database(db: FileErrorDatabase, url: str, base_path: str) -> None:
def add_new_repo_to_database(db: FileErrorDatabase, url: str, base_path: Path) -> None:

author = url.split('.git')[0].split('/')[-2]
project = url.split('.git')[0].split('/')[-1]

base_path = os.path.join(base_path, author, project)

exists_on_fs = os.path.exists(base_path)
base_path = base_path / author / project

if exists_on_fs:
if base_path.exists():
print(f'Repository {base_path} does already exist, do not clone.')
fs_repo = Repo(base_path)
else:
try:
fs_repo = Repo.clone_from(url, base_path)
except:
raise Exception(f'Failed cloning repository from `{url}`!')
except Exception as ex:
raise Exception(f'Failed cloning repository from `{url}`!\n{ex}')

commit = fs_repo.head.commit

Expand All @@ -57,16 +58,16 @@ def add_new_repo_to_database(db: FileErrorDatabase, url: str, base_path: str) ->
files = get_files_of_interest(base_path, ExtensionsOfInterest)

for file in files:
file = os.path.join('.', os.path.relpath(file, base_path))
file = Path(os.path.join('.', os.path.relpath(file, base_path)))
repo_file = RepoFile(path=file, errors=99999)

if not db.isFileInRepo(repo, repo_file):
db.addFileToRepo(repo, repo_file)

db.addRepo(repo)

def write_back_err_count(db: FileErrorDatabase, path_err_cnt_log: str, path_thirdparty_designs: str) -> None:
with open(path_err_cnt_log, 'r') as f:
def write_back_err_count(db: FileErrorDatabase, path_err_cnt_log: Path, path_thirdparty_designs: Path) -> None:
with path_err_cnt_log.open() as f:
log = f.readlines()

for line in log:
Expand All @@ -78,23 +79,23 @@ def write_back_err_count(db: FileErrorDatabase, path_err_cnt_log: str, path_thir
expect_err = int(matches[1])
file_path = str(matches[2])

author = file_path[len(path_thirdparty_designs):].split(os.path.sep)[1]
project = file_path[len(path_thirdparty_designs):].split(os.path.sep)[2]
author = file_path[len(str(path_thirdparty_designs)):].split(os.path.sep)[1]
project = file_path[len(str(path_thirdparty_designs)):].split(os.path.sep)[2]

path_repo = os.path.join(path_thirdparty_designs, author, project)
path_repo = path_thirdparty_designs / author / project

# Make path relative
file_path = os.path.relpath(file_path, path_repo)
file_path = os.path.join('.', file_path)
file_path = Path(os.path.join('.', file_path))

repo = db.getRepoByNames(author, project)
file = db.getFileByPath(repo, file_path)

db.updateErrorCounter(file, actual_err)


def create_repo_cpp_unit_test(repo: Repository, path_repo: str, path_unit_test: str) -> None:
with open(path_unit_test, 'w') as f:
def create_repo_cpp_unit_test(repo: Repository, path_repo: Path, path_unit_test: Path) -> None:
with path_unit_test.open('w', encoding='utf-8') as f:
preamble = """// THIS FILE IS AUTOMATICALLY GENERATED! DO NOT MODIFY IT!


Expand All @@ -113,15 +114,15 @@ def create_repo_cpp_unit_test(repo: Repository, path_repo: str, path_unit_test:

for file in repo.files:
file_name = os.path.basename(file.path)
full_path = os.path.normpath(os.path.join(path_repo, file.path))
full_path = Path(os.path.normpath(path_repo / file.path))
unit_test = f"""


TEST_CASE("{repo.author} - {repo.project} - {file_name} : Check File {full_path}", "[Misc]")
TEST_CASE("{repo.author} - {repo.project} - {file_name} : Check File {full_path.as_posix()}", "[Misc]")
{{
configure_spdlog();

const fs::path inputFile{{"{full_path}"}};
const fs::path inputFile{{"{full_path.as_posix()}"}};

OOCP::ParserConfig cfg = get_parser_config();

Expand Down Expand Up @@ -195,19 +196,19 @@ def create_repo_cpp_unit_test(repo: Repository, path_repo: str, path_unit_test:
do_write_back = args.write_back
do_download = args.do_download

path_thirdparty_designs = args.path_thirdparty_designs
path_unit_tests = args.path_unit_tests
path_thirdparty_designs = Path(args.path_thirdparty_designs)
path_unit_tests = Path(args.path_unit_tests)
path_err_cnt_log = args.path_err_cnt_log

path_db = args.path_db

if not do_generate_unit_tests and not do_write_back and not do_download:
parser.print_help()

def generate_unit_tests(db: FileErrorDatabase, path_thirdparty_designs: str, path_unit_tests: str) -> None:
def generate_unit_tests(db: FileErrorDatabase, path_thirdparty_designs: Path, path_unit_tests: Path) -> None:
for repo in db.data.repositories:
path_repo = os.path.join(path_thirdparty_designs, repo.author, repo.project)
path_unit_test = os.path.join(path_unit_tests, f'Test_{repo.author}_{repo.project}.cpp')
path_repo = path_thirdparty_designs / repo.author / repo.project
path_unit_test = path_unit_tests / f'Test_{repo.author}_{repo.project}.cpp'

create_repo_cpp_unit_test(repo, path_repo, path_unit_test)

Expand Down
2 changes: 1 addition & 1 deletion test/src/Helper.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ inline void check_error_count(const fs::path& aFilePath, size_t aActualErrCnt, s
// that want to write to this file.
while(true)
{
std::FILE* lockFile = std::fopen(lockFilePath.c_str(), "ax");
std::FILE* lockFile = std::fopen(lockFilePath.string().c_str(), "ax");

if(nullptr != lockFile)
{
Expand Down
Loading