Skip to content

Commit 8bcebf7

Browse files
authored
Merge pull request #319 from splunk/use_output_redirect_for_modinput_tests
removed forcing to bytes or text, test stdout/err with pytest fixtures
2 parents 91a638a + f5e21ef commit 8bcebf7

File tree

4 files changed

+293
-321
lines changed

4 files changed

+293
-321
lines changed

splunklib/modularinput/event_writer.py

Lines changed: 9 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
import sys
1717

1818
from io import TextIOWrapper, TextIOBase
19-
from splunklib.six import ensure_text
19+
from splunklib.six import ensure_str
2020
from .event import ET
2121

2222
try:
@@ -43,15 +43,8 @@ def __init__(self, output = sys.stdout, error = sys.stderr):
4343
:param output: Where to write the output; defaults to sys.stdout.
4444
:param error: Where to write any errors; defaults to sys.stderr.
4545
"""
46-
if isinstance(output, TextIOBase):
47-
self._out = output
48-
else:
49-
self._out = TextIOWrapper(output)
50-
51-
if isinstance(error, TextIOBase):
52-
self._err = error
53-
else:
54-
self._err = TextIOWrapper(error)
46+
self._out = output
47+
self._err = error
5548

5649
# has the opening <stream> tag been written yet?
5750
self.header_written = False
@@ -63,18 +56,20 @@ def write_event(self, event):
6356
"""
6457

6558
if not self.header_written:
66-
self._out.write(ensure_text("<stream>"))
59+
self._out.write("<stream>")
6760
self.header_written = True
6861

6962
event.write_to(self._out)
7063

7164
def log(self, severity, message):
7265
"""Logs messages about the state of this modular input to Splunk.
7366
These messages will show up in Splunk's internal logs.
67+
7468
:param severity: ``string``, severity of message, see severities defined as class constants.
7569
:param message: ``string``, message to log.
7670
"""
77-
self._err.write(ensure_text("%s %s\n" % (severity, message)))
71+
72+
self._err.write("%s %s\n" % (severity, message))
7873
self._err.flush()
7974

8075
def write_xml_document(self, document):
@@ -83,11 +78,10 @@ def write_xml_document(self, document):
8378
8479
:param document: An ``ElementTree`` object.
8580
"""
86-
data = ET.tostring(document)
87-
self._out.write(ensure_text(data))
81+
self._out.write(ensure_str(ET.tostring(document)))
8882
self._out.flush()
8983

9084
def close(self):
9185
"""Write the closing </stream> tag to make this XML well formed."""
92-
self._out.write(ensure_text("</stream>"))
86+
self._out.write("</stream>")
9387
self._out.flush()

splunklib/modularinput/script.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -105,8 +105,7 @@ def run_script(self, args, event_writer, input_stream):
105105
return 1
106106

107107
except Exception as e:
108-
err_string = EventWriter.ERROR + str(e)
109-
event_writer._err.write(err_string)
108+
event_writer.log(EventWriter.ERROR, str(e))
110109
return 1
111110

112111
@property

tests/modularinput/test_event.py

Lines changed: 120 additions & 124 deletions
Original file line numberDiff line numberDiff line change
@@ -15,143 +15,139 @@
1515
# under the License.
1616

1717
from __future__ import absolute_import
18+
19+
import sys
20+
21+
import pytest
22+
1823
from tests.modularinput.modularinput_testlib import unittest, xml_compare, data_open
1924
from splunklib.modularinput.event import Event, ET
2025
from splunklib.modularinput.event_writer import EventWriter
21-
from io import BytesIO, TextIOWrapper
22-
23-
try:
24-
from splunklib.six.moves import cStringIO as StringIO
25-
except ImportError:
26-
from splunklib.six import StringIO
27-
28-
29-
class EventTestCase(unittest.TestCase):
30-
def test_event_without_enough_fields_fails(self):
31-
"""Check that events without data throw an error"""
32-
with self.assertRaises(ValueError):
33-
event = Event()
34-
stream = StringIO()
35-
event.write_to(stream)
36-
self.assertTrue(True)
37-
38-
def test_xml_of_event_with_minimal_configuration(self):
39-
"""Generate XML from an event object with a small number of fields,
40-
and see if it matches what we expect."""
41-
stream = BytesIO()
42-
43-
event = Event(
44-
data="This is a test of the emergency broadcast system.",
45-
stanza="fubar",
46-
time="%.3f" % 1372187084.000
47-
)
48-
49-
event.write_to(stream)
50-
51-
constructed = ET.fromstring(stream.getvalue())
52-
expected = ET.parse(data_open("data/event_minimal.xml")).getroot()
53-
54-
self.assertTrue(xml_compare(expected, constructed))
55-
56-
def test_xml_of_event_with_more_configuration(self):
57-
"""Generate XML from an even object with all fields set, see if
58-
it matches what we expect"""
59-
stream = BytesIO()
60-
61-
event = Event(
62-
data="This is a test of the emergency broadcast system.",
63-
stanza="fubar",
64-
time="%.3f" % 1372274622.493,
65-
host="localhost",
66-
index="main",
67-
source="hilda",
68-
sourcetype="misc",
69-
done=True,
70-
unbroken=True
71-
)
72-
event.write_to(stream)
73-
74-
constructed = ET.fromstring(stream.getvalue())
75-
expected = ET.parse(data_open("data/event_maximal.xml")).getroot()
76-
77-
self.assertTrue(xml_compare(expected, constructed))
78-
79-
def test_writing_events_on_event_writer(self):
80-
"""Write a pair of events with an EventWriter, and ensure that they
81-
are being encoded immediately and correctly onto the output stream"""
82-
out = BytesIO()
83-
err = BytesIO()
84-
85-
ew = EventWriter(out, err)
86-
87-
e = Event(
88-
data="This is a test of the emergency broadcast system.",
89-
stanza="fubar",
90-
time="%.3f" % 1372275124.466,
91-
host="localhost",
92-
index="main",
93-
source="hilda",
94-
sourcetype="misc",
95-
done=True,
96-
unbroken=True
97-
)
98-
ew.write_event(e)
99-
100-
found = ET.fromstring("%s</stream>" % out.getvalue().decode('utf-8'))
101-
expected = ET.parse(data_open("data/stream_with_one_event.xml")).getroot()
10226

103-
self.assertTrue(xml_compare(expected, found))
104-
self.assertEqual(err.getvalue(), b"")
10527

28+
def test_event_without_enough_fields_fails(capsys):
29+
"""Check that events without data throw an error"""
30+
with pytest.raises(ValueError), capsys.disabled():
31+
event = Event()
32+
event.write_to(sys.stdout)
33+
34+
def test_xml_of_event_with_minimal_configuration(capsys):
35+
"""Generate XML from an event object with a small number of fields,
36+
and see if it matches what we expect."""
37+
38+
event = Event(
39+
data="This is a test of the emergency broadcast system.",
40+
stanza="fubar",
41+
time="%.3f" % 1372187084.000
42+
)
43+
44+
event.write_to(sys.stdout)
45+
46+
captured = capsys.readouterr()
47+
constructed = ET.fromstring(captured.out)
48+
with data_open("data/event_minimal.xml") as data:
49+
expected = ET.parse(data).getroot()
50+
51+
assert xml_compare(expected, constructed)
52+
53+
def test_xml_of_event_with_more_configuration(capsys):
54+
"""Generate XML from an even object with all fields set, see if
55+
it matches what we expect"""
56+
57+
event = Event(
58+
data="This is a test of the emergency broadcast system.",
59+
stanza="fubar",
60+
time="%.3f" % 1372274622.493,
61+
host="localhost",
62+
index="main",
63+
source="hilda",
64+
sourcetype="misc",
65+
done=True,
66+
unbroken=True
67+
)
68+
event.write_to(sys.stdout)
69+
70+
captured = capsys.readouterr()
71+
72+
constructed = ET.fromstring(captured.out)
73+
with data_open("data/event_maximal.xml") as data:
74+
expected = ET.parse(data).getroot()
75+
76+
assert xml_compare(expected, constructed)
77+
78+
def test_writing_events_on_event_writer(capsys):
79+
"""Write a pair of events with an EventWriter, and ensure that they
80+
are being encoded immediately and correctly onto the output stream"""
81+
82+
ew = EventWriter(sys.stdout, sys.stderr)
83+
84+
e = Event(
85+
data="This is a test of the emergency broadcast system.",
86+
stanza="fubar",
87+
time="%.3f" % 1372275124.466,
88+
host="localhost",
89+
index="main",
90+
source="hilda",
91+
sourcetype="misc",
92+
done=True,
93+
unbroken=True
94+
)
95+
ew.write_event(e)
96+
97+
captured = capsys.readouterr()
98+
99+
first_out_part = captured.out
100+
101+
with data_open("data/stream_with_one_event.xml") as data:
102+
found = ET.fromstring("%s</stream>" % first_out_part)
103+
expected = ET.parse(data).getroot()
104+
105+
assert xml_compare(expected, found)
106+
assert captured.err == ""
107+
108+
ew.write_event(e)
109+
ew.close()
110+
111+
captured = capsys.readouterr()
112+
with data_open("data/stream_with_two_events.xml") as data:
113+
found = ET.fromstring(first_out_part + captured.out)
114+
expected = ET.parse(data).getroot()
115+
116+
assert xml_compare(expected, found)
117+
118+
def test_error_in_event_writer():
119+
"""An event which cannot write itself onto an output stream
120+
(such as because it doesn't have a data field set)
121+
should write an error. Check that it does so."""
122+
123+
ew = EventWriter(sys.stdout, sys.stderr)
124+
e = Event()
125+
with pytest.raises(ValueError) as excinfo:
106126
ew.write_event(e)
107-
ew.close()
127+
assert str(excinfo.value) == "Events must have at least the data field set to be written to XML."
108128

109-
found = ET.fromstring(out.getvalue())
110-
expected = ET.parse(data_open("data/stream_with_two_events.xml")).getroot()
129+
def test_logging_errors_with_event_writer(capsys):
130+
"""Check that the log method on EventWriter produces the
131+
expected error message."""
111132

112-
self.assertTrue(xml_compare(expected, found))
133+
ew = EventWriter(sys.stdout, sys.stderr)
113134

114-
def test_error_in_event_writer(self):
115-
"""An event which cannot write itself onto an output stream
116-
(such as because it doesn't have a data field set)
117-
should write an error. Check that it does so."""
118-
out = BytesIO()
119-
err = BytesIO()
135+
ew.log(EventWriter.ERROR, "Something happened!")
120136

121-
ew = EventWriter(out, err)
122-
e = Event()
123-
try:
124-
ew.write_event(e)
125-
self.assertTrue(False)
126-
except ValueError as e:
127-
self.assertEqual("Events must have at least the data field set to be written to XML.", str(e))
137+
captured = capsys.readouterr()
138+
assert captured.err == "ERROR Something happened!\n"
128139

129-
def test_logging_errors_with_event_writer(self):
130-
"""Check that the log method on EventWriter produces the
131-
expected error message."""
132-
out = BytesIO()
133-
err = BytesIO()
140+
def test_write_xml_is_sane(capsys):
141+
"""Check that EventWriter.write_xml_document writes sensible
142+
XML to the output stream."""
134143

135-
ew = EventWriter(out, err)
144+
ew = EventWriter(sys.stdout, sys.stderr)
136145

137-
ew.log(EventWriter.ERROR, "Something happened!")
138-
139-
self.assertEqual(b"ERROR Something happened!\n", err.getvalue())
140-
141-
def test_write_xml_is_sane(self):
142-
"""Check that EventWriter.write_xml_document writes sensible
143-
XML to the output stream."""
144-
out = BytesIO()
145-
err = BytesIO()
146-
147-
ew = EventWriter(out, err)
148-
149-
expected_xml = ET.parse(data_open("data/event_maximal.xml")).getroot()
146+
with data_open("data/event_maximal.xml") as data:
147+
expected_xml = ET.parse(data).getroot()
150148

151149
ew.write_xml_document(expected_xml)
152-
found_xml = ET.fromstring(out.getvalue())
153-
154-
self.assertTrue(xml_compare(expected_xml, found_xml))
150+
captured = capsys.readouterr()
151+
found_xml = ET.fromstring(captured.out)
155152

156-
if __name__ == "__main__":
157-
unittest.main()
153+
assert xml_compare(expected_xml, found_xml)

0 commit comments

Comments
 (0)