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

Modified e2e regression tests to reproduce only one bug #275

Merged
merged 8 commits into from
Nov 1, 2023
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
6 changes: 3 additions & 3 deletions .github/workflows/e2e-test.yml
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
name: End-to-End Test
on:
pull_request:
schedule:
- cron: '0 0 * * 0' # Run every Sunday at 00:00 UTC
# schedule:
# - cron: '0 0 * * 0' # Run every Sunday at 00:00 UTC
jobs:
bug_reproduction:
timeout-minutes: 1440
Expand All @@ -26,4 +26,4 @@ jobs:
mkdir -m 777 -p profile/data
- name: Run bug reproduction
run: |
pytest -m "local"
pytest -m "singleBugReproduction"
2 changes: 1 addition & 1 deletion .github/workflows/python-syntax-checker.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ jobs:
make
- name: Run unittest
run: |
pytest -m "not local" --junitxml=pytest.xml --cov-report=term-missing:skip-covered --cov=acto | tee pytest-coverage.txt
pytest -m "not local and not singleBugReproduction" --junitxml=pytest.xml --cov-report=term-missing:skip-covered --cov=acto | tee pytest-coverage.txt
- name: Pytest coverage comment
uses: MishaKav/pytest-coverage-comment@main
with:
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/unittest.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,4 @@ jobs:
make
- name: Run unittest
run: |
pytest -m "not local"
pytest -m "not local and not singleBugReproduction"
5 changes: 4 additions & 1 deletion acto/runner/runner.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import base64
import queue
import time
from multiprocessing import Process, Queue
from multiprocessing import Process, Queue, set_start_method, get_start_method

import yaml

Expand Down Expand Up @@ -60,6 +60,9 @@ def __init__(self,
'role_binding': self.rbacAuthorizationV1Api.list_namespaced_role_binding,
}

if get_start_method() != "fork":
set_start_method("fork")

def run(self, input: dict, generation: int) -> Tuple[Snapshot, bool]:
'''Simply run the cmd and dumps system_state, delta, operator log, events and input files without checking.
The function blocks until system converges.
Expand Down
3 changes: 2 additions & 1 deletion pytest.ini
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
[pytest]
markers =
local: mark a test to run on a local machine
local: mark a test to run on a local machine
singleBugReproduction: mark a test to run e2e regressions on a pull request
36 changes: 36 additions & 0 deletions test/test_bug_reproduction.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import os
import pathlib
import queue
import random
from typing import Dict, List, Tuple
import unittest

Expand Down Expand Up @@ -118,6 +119,7 @@ class TestBugReproduction(unittest.TestCase):
def __init__(self, methodName: str = "runTest") -> None:
super().__init__(methodName)

# TODO: make _num_workers a command line argument
self._num_workers = 2 # Number of workers to run the test

def test_all_bugs(self):
Expand Down Expand Up @@ -146,6 +148,40 @@ def test_all_bugs(self):

self.assertFalse(errors, f'Test failed with {errors}')

@pytest.mark.singleBugReproduction
class TestSingleBugReproduction(unittest.TestCase):

def __init__(self, methodName: str = "runTest") -> None:
super().__init__(methodName)

self._num_workers = 1 # Number of workers to run the test

def test_all_bugs(self):
manager = multiprocessing.Manager()
workqueue = multiprocessing.Queue()

operator, bugs = random.choice(list(all_bugs.items()))
bug_id, bug_config = random.choice(list(bugs.items()))
workqueue.put((operator, bug_id, bug_config))

reproduction_results: Dict[str, bool] = manager.dict() # workers write reproduction results
# to this dict. Bug ID -> if success
processes: List[multiprocessing.Process] = []
for i in range(self._num_workers):
p = multiprocessing.Process(target=run_worker, args=(workqueue, i, reproduction_results))
p.start()
processes.append(p)

for p in processes:
p.join()

errors = []
for bug_id, if_reproduced in reproduction_results.items():
if not if_reproduced:
errors.append(bug_id)

self.assertFalse(errors, f'Test failed with {errors}')


if __name__ == '__main__':
unittest.main()