Skip to content

Commit d3111a6

Browse files
fix: handling infinite loop (#812)
There was a bug in PSA where if in splunk_ingest_data first worker errors out or throws exception then it does not write to a file, now other workers would be waiting indefinitely for the file to be present, So the execution would continue in infinitly. To handle this scenario, we can handle the exception thrown by the first worker and make sure that in any case it writes to a file, so that other workers don't wait indefinitly
1 parent 6a16609 commit d3111a6

File tree

3 files changed

+73
-28
lines changed

3 files changed

+73
-28
lines changed

.github/workflows/build-test-release.yml

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -120,18 +120,15 @@ jobs:
120120
run: |
121121
pip install git+https://github.com/pixelb/crudini
122122
mkdir test-results-${{ matrix.splunk.version }}
123-
- name: Splunk Up
123+
- name: Test
124124
run: |
125-
export SPLUNK_APP_PACKAGE=./tests/e2e/addons/TA_fiction
126-
export SPLUNK_ADDON=TA_fiction
127-
export SPLUNK_APP_ID=TA_fiction
125+
export SPLUNK_APP_PACKAGE=./tests/e2e/addons/TA_fiction_indextime
126+
export SPLUNK_ADDON=TA_fiction_indextime
127+
export SPLUNK_APP_ID=TA_fiction_indextime
128128
export SPLUNK_VERSION=${{ matrix.splunk.version }}
129+
export SPLUNK_HEC_TOKEN="9b741d03-43e9-4164-908b-e09102327d22"
129130
echo $SPLUNK_VERSION
130131
docker compose -f "docker-compose-ci.yml" build
131-
SPLUNK_PASSWORD=Chang3d! docker compose -f docker-compose-ci.yml up -d splunk
132-
sleep 90
133-
- name: Test
134-
run: |
135132
SPLUNK_PASSWORD=Chang3d! docker compose -f docker-compose-ci.yml up --abort-on-container-exit
136133
docker volume ls
137134
- name: Collect Results

pytest_splunk_addon/splunk.py

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -750,18 +750,21 @@ def splunk_ingest_data(request, splunk_hec_uri, sc4s, uf, splunk_events_cleanup)
750750
}
751751
thread_count = int(request.config.getoption("thread_count"))
752752
store_events = request.config.getoption("store_events")
753-
IngestorHelper.ingest_events(
754-
ingest_meta_data,
755-
addon_path,
756-
config_path,
757-
thread_count,
758-
store_events,
759-
)
760-
sleep(50)
761-
if "PYTEST_XDIST_WORKER" in os.environ:
762-
with open(os.environ.get("PYTEST_XDIST_TESTRUNUID") + "_wait", "w+"):
763-
PYTEST_XDIST_TESTRUNUID = os.environ.get("PYTEST_XDIST_TESTRUNUID")
764-
753+
try:
754+
IngestorHelper.ingest_events(
755+
ingest_meta_data,
756+
addon_path,
757+
config_path,
758+
thread_count,
759+
store_events,
760+
)
761+
sleep(50)
762+
except Exception as e:
763+
raise e
764+
finally:
765+
if "PYTEST_XDIST_WORKER" in os.environ:
766+
with open(os.environ.get("PYTEST_XDIST_TESTRUNUID") + "_wait", "w+"):
767+
PYTEST_XDIST_TESTRUNUID = os.environ.get("PYTEST_XDIST_TESTRUNUID")
765768
else:
766769
while not os.path.exists(os.environ.get("PYTEST_XDIST_TESTRUNUID") + "_wait"):
767770
sleep(1)

tests/e2e/test_splunk_addon.py

Lines changed: 53 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ def test_splunk_connection_external(testdir, request):
8484
# fnmatch_lines does an assertion internally
8585
result.assert_outcomes(passed=1, failed=0)
8686

87-
# make sure that that we get a '0' exit code for the testsuite
87+
# make sure that we get a '0' exit code for the testsuite
8888
assert result.ret == 0
8989

9090

@@ -117,7 +117,7 @@ def test_splunk_connection_docker(testdir, request):
117117
# fnmatch_lines does an assertion internally
118118
result.assert_outcomes(passed=1, failed=0)
119119

120-
# make sure that that we get a '0' exit code for the testsuite
120+
# make sure that we get a '0' exit code for the testsuite
121121
assert result.ret == 0
122122

123123

@@ -165,7 +165,7 @@ def empty_method():
165165
skipped=len(constants.TA_FICTION_SKIPPED),
166166
)
167167

168-
# make sure that that we get a '0' exit code for the testsuite
168+
# make sure that we get a '0' exit code for the testsuite
169169
assert result.ret == 0
170170

171171

@@ -328,7 +328,7 @@ def empty_method():
328328
skipped=len(constants.TA_CIM_FICTION_SKIPPED),
329329
)
330330

331-
# make sure that that we get a '0' exit code for the testsuite
331+
# make sure that we get a '0' exit code for the testsuite
332332
assert result.ret == 0
333333

334334

@@ -439,7 +439,7 @@ def empty_method():
439439
failed=0,
440440
)
441441

442-
# make sure that that we get a '0' exit code for the testsuite
442+
# make sure that we get a '0' exit code for the testsuite
443443
assert result.ret == 0
444444

445445

@@ -627,7 +627,7 @@ def empty_method():
627627
skipped=len(constants.TA_REQ_TRANSITION_SKIPPED),
628628
)
629629

630-
# make sure that that we get a non '0' exit code for the testsuite as it contains failure
630+
# make sure that we get a non '0' exit code for the testsuite as it contains failure
631631
assert result.ret == 0, "result not equal to 0"
632632

633633

@@ -682,7 +682,7 @@ def empty_method():
682682
skipped=len(constants.TA_REQ_BROKEN_SKIPPED),
683683
)
684684

685-
# make sure that that we get a non '0' exit code for the testsuite as it contains failure
685+
# make sure that we get a non '0' exit code for the testsuite as it contains failure
686686
assert result.ret != 0
687687

688688

@@ -737,5 +737,50 @@ def empty_method():
737737
skipped=len(constants.TA_REQ_TRANSITION_SKIPPED),
738738
)
739739

740-
# make sure that that we get a non '0' exit code for the testsuite as it contains failure
740+
# make sure that we get a non '0' exit code for the testsuite as it contains failure
741741
assert result.ret == 0, "result not equal to 0"
742+
743+
744+
@pytest.mark.test_infinite_loop_fixture
745+
@pytest.mark.external
746+
def test_infinite_loop_in_ingest_data_fixture(testdir, request):
747+
"""Make sure that pytest accepts our fixture."""
748+
749+
testdir.makepyfile(
750+
"""
751+
from pytest_splunk_addon.standard_lib.addon_basic import Basic
752+
class Test_App(Basic):
753+
def empty_method():
754+
pass
755+
"""
756+
)
757+
758+
shutil.copytree(
759+
os.path.join(testdir.request.fspath.dirname, "addons/TA_fiction_indextime"),
760+
os.path.join(testdir.tmpdir, "package"),
761+
)
762+
763+
shutil.copytree(
764+
os.path.join(testdir.request.fspath.dirname, "test_data_models"),
765+
os.path.join(testdir.tmpdir, "tests/data_models"),
766+
)
767+
768+
setup_test_dir(testdir)
769+
SampleGenerator.clean_samples()
770+
Rule.clean_rules()
771+
772+
# run pytest with the following cmd args
773+
# we are providing wrong sc4s service details here so that we can recreate scenario where first worked raises exception and other workers get stuck
774+
result = testdir.runpytest(
775+
"--splunk-app=addons/TA_fiction_indextime",
776+
"--splunk-type=external",
777+
"--splunk-host=splunk",
778+
"--splunk-data-generator=tests/addons/TA_fiction_indextime/default",
779+
"--sc4s-host=splunk",
780+
"--sc4s-port=100",
781+
"-n 2",
782+
)
783+
784+
# Here we are not interested in the failures or errors,
785+
# we are basically checking that we get results and test execution does not get stuck
786+
assert result.parseoutcomes().get("passed") > 0

0 commit comments

Comments
 (0)