Skip to content

Commit b11e19f

Browse files
author
rfaircloth-splunk
committed
Merge branch 'develop' of github.com:splunk/pytest-splunk-addon into develop
merged
2 parents d9f8cad + b33af24 commit b11e19f

File tree

6 files changed

+471
-428
lines changed

6 files changed

+471
-428
lines changed

pytest_splunk_addon/plugin.py

Lines changed: 82 additions & 112 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,8 @@ def pytest_configure(config):
1919
"""
2020
Setup configuration after command-line options are parsed
2121
"""
22-
config.addinivalue_line(
23-
"markers", "splunk_addon_internal_errors: Check Errors"
24-
)
25-
config.addinivalue_line(
26-
"markers", "splunk_addon_searchtime: Test search time only"
27-
)
22+
config.addinivalue_line("markers", "splunk_addon_internal_errors: Check Errors")
23+
config.addinivalue_line("markers", "splunk_addon_searchtime: Test search time only")
2824

2925

3026
def dedup_tests(test_list):
@@ -48,13 +44,9 @@ def pytest_generate_tests(metafunc):
4844
"""
4945
for fixture in metafunc.fixturenames:
5046
if fixture.startswith("splunk_app"):
51-
LOGGER.info(
52-
"generating testcases for splunk_app. fixture=%s", fixture
53-
)
47+
LOGGER.info("generating testcases for splunk_app. fixture=%s", fixture)
5448
# Load associated test data
55-
tests = load_splunk_tests(
56-
metafunc.config.getoption("splunk_app"), fixture
57-
)
49+
tests = load_splunk_tests(metafunc.config.getoption("splunk_app"), fixture)
5850
metafunc.parametrize(fixture, dedup_tests(tests))
5951

6052

@@ -129,15 +121,8 @@ def return_tags(tags_property, stanza_name):
129121
List of pytest parameters
130122
"""
131123
return pytest.param(
132-
{
133-
"tag_query": stanza_name,
134-
tags_property.value + "_tag": tags_property.name,
135-
},
136-
id=stanza_name
137-
+ " | "
138-
+ tags_property.name
139-
+ "="
140-
+ tags_property.value,
124+
{"tag_query": stanza_name, tags_property.value + "_tag": tags_property.name,},
125+
id=stanza_name + " | " + tags_property.name + "=" + tags_property.value,
141126
)
142127

143128

@@ -158,14 +143,10 @@ def load_splunk_props(props):
158143
elif props_section.startswith("source::"):
159144
LOGGER.info("Parsing source stanza=%s", props_section)
160145
for props_source in list(get_list_of_sources(props_section)):
161-
yield return_props_stanza_param(
162-
props_section, props_source, "source"
163-
)
146+
yield return_props_stanza_param(props_section, props_source, "source")
164147
else:
165148
LOGGER.info("parsing sourcetype stanza=%s", props_section)
166-
yield return_props_stanza_param(
167-
props_section, props_section, "sourcetype"
168-
)
149+
yield return_props_stanza_param(props_section, props_section, "sourcetype")
169150

170151

171152
def return_props_stanza_param(stanza_id, stanza_value, stanza_type):
@@ -192,9 +173,7 @@ def return_props_stanza_param(stanza_id, stanza_value, stanza_type):
192173
stanza_value,
193174
str(test_name),
194175
)
195-
return pytest.param(
196-
{"field": stanza_type, "value": stanza_value}, id=test_name
197-
)
176+
return pytest.param({"field": stanza_type, "value": stanza_value}, id=test_name)
198177

199178

200179
def load_splunk_fields(app, props, transforms):
@@ -247,20 +226,15 @@ def load_splunk_fields(app, props, transforms):
247226
)
248227
elif current.startswith("REPORT-"):
249228
yield from return_transforms_report(
250-
transforms,
251-
stanza_type,
252-
each_stanza_name,
253-
props_property,
229+
transforms, stanza_type, each_stanza_name, props_property,
254230
)
255-
elif re.match('LOOKUP', current, re.IGNORECASE):
231+
elif re.match("LOOKUP", current, re.IGNORECASE):
256232
yield from return_props_lookup(
257233
stanza_type, each_stanza_name, props_property, app
258-
259234
)
260235

261-
def get_params_from_regex(
262-
regex, property_value, stanza_type, stanza_name, fields
263-
):
236+
237+
def get_params_from_regex(regex, property_value, stanza_type, stanza_name, fields):
264238
"""
265239
Returns the fields captured using regex as pytest parameters
266240
@@ -283,9 +257,7 @@ def get_params_from_regex(
283257
for matchNum, match in enumerate(matches, start=1):
284258
for groupNum in range(0, len(match.groups())):
285259
groupNum = groupNum + 1
286-
field_test_name = "{}_field::{}".format(
287-
stanza_name, match.group(groupNum)
288-
)
260+
field_test_name = "{}_field::{}".format(stanza_name, match.group(groupNum))
289261
yield pytest.param(
290262
{
291263
"stanza_type": stanza_type,
@@ -297,9 +269,7 @@ def get_params_from_regex(
297269
fields.append(match.group(groupNum))
298270

299271

300-
def return_transforms_report(
301-
transforms, stanza_type, stanza_name, report_property
302-
):
272+
def return_transforms_report(transforms, stanza_type, stanza_name, report_property):
303273
"""
304274
Returns the fields parsed from transforms.conf as pytest parameters
305275
@@ -316,8 +286,7 @@ def return_transforms_report(
316286
"""
317287
try:
318288
for transforms_section in [
319-
each_stanza.strip()
320-
for each_stanza in report_property.value.split(",")
289+
each_stanza.strip() for each_stanza in report_property.value.split(",")
321290
]:
322291
report_test_name = (
323292
f"{stanza_name}::{report_property.name}::{transforms_section}"
@@ -339,27 +308,19 @@ def return_transforms_report(
339308
),
340309
)
341310
fields.append(section.options["SOURCE_KEY"].value)
342-
if (
343-
"REGEX" in section.options
344-
and section.options["REGEX"].value != ""
345-
):
346-
regex = r"\(\?<([^\>]+)\>"
311+
if "REGEX" in section.options and section.options["REGEX"].value != "":
312+
regex = r"\(\?P?(?:[<'])([^\>'\s]+)[\>']"
347313
yield from get_params_from_regex(
348314
regex,
349315
section.options["REGEX"].value,
350316
stanza_type,
351317
stanza_name,
352318
fields,
353319
)
354-
if (
355-
"FIELDS" in section.options
356-
and section.options["FIELDS"].value != ""
357-
):
320+
if "FIELDS" in section.options and section.options["FIELDS"].value != "":
358321
fields_list = [
359322
each_field.strip()
360-
for each_field in section.options["FIELDS"].value.split(
361-
","
362-
)
323+
for each_field in section.options["FIELDS"].value.split(",")
363324
]
364325
for each_field in fields_list:
365326
yield pytest.param(
@@ -371,10 +332,7 @@ def return_transforms_report(
371332
id="{}_field::{}".format(stanza_name, each_field),
372333
)
373334
fields.append(each_field)
374-
if (
375-
"FORMAT" in section.options
376-
and section.options["FORMAT"].value != ""
377-
):
335+
if "FORMAT" in section.options and section.options["FORMAT"].value != "":
378336
regex = r"(\S*)::"
379337
yield from get_params_from_regex(
380338
regex,
@@ -415,27 +373,27 @@ def return_props_extract(stanza_type, stanza_name, props_property):
415373
generator of fields as pytest parameters
416374
"""
417375
test_name = f"{stanza_name}::{props_property.name}"
418-
regex = r"\(\?<([^\>]+)\>(?:.*(?i)in\s+(.*))?"
419-
matches = re.finditer(regex, props_property.value, re.MULTILINE)
376+
regex = r"\(\?P?(?:[<'])([^\>'\s]+)[\>']"
420377
fields = []
421-
for match_num, match in enumerate(matches, start=1):
422-
for group_num in range(0, len(match.groups())):
423-
group_num = group_num + 1
424-
if match.group(group_num):
425-
field_test_name = "{}_field::{}".format(
426-
stanza_name, match.group(group_num)
427-
)
428-
yield pytest.param(
429-
{
430-
"stanza_type": stanza_type,
431-
"stanza_name": stanza_name,
432-
"fields": [match.group(group_num)],
433-
},
434-
id=field_test_name,
435-
)
436-
fields.append(match.group(group_num))
378+
yield from get_params_from_regex(
379+
regex, props_property.value, stanza_type, stanza_name, fields,
380+
)
381+
# If SOURCE_KEY is used in EXTRACT, generate the test for the same.
382+
regex_for_source_key = r"(?:(?i)in\s+(\w+))\s*$"
383+
extract_source_key = re.search(
384+
regex_for_source_key, props_property.value, re.MULTILINE
385+
)
386+
if extract_source_key:
387+
yield pytest.param(
388+
{
389+
"stanza_type": stanza_type,
390+
"stanza_name": stanza_name,
391+
"fields": extract_source_key.group(1),
392+
},
393+
id="{}_field::{}".format(stanza_name, extract_source_key.group(1)),
394+
)
395+
fields.insert(0, extract_source_key.group(1))
437396
if fields:
438-
fields.reverse()
439397
LOGGER.info(
440398
"(Generated pytest.param for extract."
441399
"stanza_type=%s stanza_name=%s, fields=%s)",
@@ -444,11 +402,7 @@ def return_props_extract(stanza_type, stanza_name, props_property):
444402
str(fields),
445403
)
446404
yield pytest.param(
447-
{
448-
"stanza_type": stanza_type,
449-
"stanza_name": stanza_name,
450-
"fields": fields,
451-
},
405+
{"stanza_type": stanza_type, "stanza_name": stanza_name, "fields": fields,},
452406
id=test_name,
453407
)
454408

@@ -477,9 +431,10 @@ def get_lookup_fields(lookup_str):
477431
lookup_str += " OUTPUT "
478432

479433
# Take input fields or output fields depending on the input_output_index
480-
input_output_str = lookup_str.split(" OUTPUT ")[input_output_index].split(" OUTPUTNEW ")[input_output_index]
434+
input_output_str = lookup_str.split(" OUTPUT ")[input_output_index].split(
435+
" OUTPUTNEW "
436+
)[input_output_index]
481437

482-
483438
field_parser = r"(\"(?:\\\"|[^\"])*\"|\'(?:\\\'|[^\'])*\'|[^\s,]+)\s*(?:[aA][sS]\s*(\"(?:\\\"|[^\"])*\"|\'(?:\\\'|[^\'])*\'|[^\s,]+))?"
484439
# field_groups: Group of max 2 fields - (source, destination) for "source as destination"
485440
field_groups = re.findall(field_parser, input_output_str)
@@ -489,11 +444,17 @@ def get_lookup_fields(lookup_str):
489444
# Taking last non-empty field ensures that the aliased value will have
490445
# higher priority
491446
for each_group in field_groups:
492-
field_list.append([each_field for each_field in reversed(each_group) if each_field][0])
447+
field_list.append(
448+
[each_field for each_field in reversed(each_group) if each_field][0]
449+
)
493450

494451
input_output_field_list.append(field_list)
495452

496-
return {"input_fields": input_output_field_list[0], "output_fields": input_output_field_list[1], "lookup_stanza": lookup_stanza}
453+
return {
454+
"input_fields": input_output_field_list[0],
455+
"output_fields": input_output_field_list[1],
456+
"lookup_stanza": lookup_stanza,
457+
}
497458

498459

499460
def return_props_lookup(stanza_type, stanza_name, props_property, app):
@@ -530,10 +491,12 @@ def return_props_lookup(stanza_type, stanza_name, props_property, app):
530491

531492
if parsed_fields["lookup_stanza"] in transforms.sects:
532493
stanza = transforms.sects[parsed_fields["lookup_stanza"]]
533-
if 'filename' in stanza.options:
534-
lookup_file = stanza.options['filename'].value
494+
if "filename" in stanza.options:
495+
lookup_file = stanza.options["filename"].value
535496
try:
536-
location = os.path.join(app.package.working_app_path, "lookups", lookup_file)
497+
location = os.path.join(
498+
app.package.working_app_path, "lookups", lookup_file
499+
)
537500
with open(location, "r") as csv_file:
538501
reader = csv.DictReader(csv_file)
539502
fieldnames = reader.fieldnames
@@ -544,16 +507,33 @@ def return_props_lookup(stanza_type, stanza_name, props_property, app):
544507
# If there is an error. the test should fail with the current fields
545508
# This makes sure the test doesn't exit prematurely
546509
except (OSError, IOError, UnboundLocalError, TypeError) as e:
547-
LOGGER.info("Could not read the lookup file, skipping test. error=%s", str(e))
510+
LOGGER.info(
511+
"Could not read the lookup file, skipping test. error=%s",
512+
str(e),
513+
)
548514

549515
# Test individual fields
550516
for each_field in lookup_field_list:
551517
field_test_name = f"{stanza_name}_field::{each_field}"
552-
yield pytest.param({'stanza_type': stanza_type, 'stanza_name': stanza_name, 'fields': [each_field]}, id=field_test_name)
518+
yield pytest.param(
519+
{
520+
"stanza_type": stanza_type,
521+
"stanza_name": stanza_name,
522+
"fields": [each_field],
523+
},
524+
id=field_test_name,
525+
)
553526

554527
# Test Lookup as a whole
555-
yield pytest.param({'stanza_type': stanza_type, 'stanza_name': stanza_name, 'fields': lookup_field_list}, id=test_name)
556-
528+
yield pytest.param(
529+
{
530+
"stanza_type": stanza_type,
531+
"stanza_name": stanza_name,
532+
"fields": lookup_field_list,
533+
},
534+
id=test_name,
535+
)
536+
557537

558538
def return_props_eval(stanza_type, stanza_name, props_property):
559539
"""
@@ -586,11 +566,7 @@ def return_props_eval(stanza_type, stanza_name, props_property):
586566
)
587567
test_name = f"{stanza_name}_field::{fields[0]}"
588568
return pytest.param(
589-
{
590-
"stanza_type": stanza_type,
591-
"stanza_name": stanza_name,
592-
"fields": fields,
593-
},
569+
{"stanza_type": stanza_type, "stanza_name": stanza_name, "fields": fields,},
594570
id=test_name,
595571
)
596572

@@ -619,11 +595,7 @@ def return_props_sourcetype(stanza_type, stanza_name, props_property):
619595
str(fields),
620596
)
621597
return pytest.param(
622-
{
623-
"stanza_type": stanza_type,
624-
"stanza_name": stanza_name,
625-
"fields": fields,
626-
},
598+
{"stanza_type": stanza_type, "stanza_name": stanza_name, "fields": fields,},
627599
id=test_name,
628600
)
629601

@@ -730,10 +702,8 @@ def return_eventtypes_param(stanza_id):
730702
"""
731703

732704
LOGGER.info(
733-
"Generated pytest.param of eventtype with id=%s",
734-
f"eventtype::{stanza_id}",
705+
"Generated pytest.param of eventtype with id=%s", f"eventtype::{stanza_id}",
735706
)
736707
return pytest.param(
737-
{"field": "eventtype", "value": stanza_id},
738-
id=f"eventtype::{stanza_id}",
708+
{"field": "eventtype", "value": stanza_id}, id=f"eventtype::{stanza_id}",
739709
)

0 commit comments

Comments
 (0)