Skip to content

Commit 18f0082

Browse files
Integration tests for send-to commands. (#212)
* Added docker and syslog server setup for send-to commands * intermittent commit * integration-tests-data-transfer * add send-to commands in other features * use ncat command to create server * fix style * fix git rebase error * Added docker and syslog server setup for send-to commands * intermittent commit * integration-tests-data-transfer * add send-to commands in other features * use ncat command to create server * fix style * fix git rebase error * use cli runner for integration tests * use cli runner in other integration tests * renamed command option to its new name * use cli runner for legalhold * fix style * removed command_runner * renamed method * remove pexpect dependency * Added dependency note for testing send-to commands. * append profile after the command * fix style * remove unnecessary state object, delete profile first in case stored creds are bad, fail fast on profile creation errors * unused import * dangling comma * remove obj and duplicate append_profile * remove obj from assert_test_is_successful * update assert_test_is_successful usage, remove last obj usages * rename test method names to appropriately * make parameterized options more readable * removed all filter options and choice options from integration tests Co-authored-by: Tim Abramson <[email protected]>
1 parent 486ea39 commit 18f0082

11 files changed

+179
-180
lines changed

CONTRIBUTING.md

+2
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,8 @@ If you want to run the integration tests in your current python environment, you
130130
pytest -m "integration"
131131
```
132132

133+
Integration tests have a dependency on `nmap` module to test `send-to` commands.
134+
133135
### Writing tests
134136

135137
Put actual before expected values in assert statements. Pytest assumes this order.

tests/conftest.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
TEST_ID = "TEST_ID"
1414

1515

16-
@pytest.fixture
16+
@pytest.fixture(scope="session")
1717
def runner():
1818
return CliRunner()
1919

tests/integration/conftest.py

+19-41
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,35 @@
11
import os
2-
from contextlib import contextmanager
2+
from shlex import split as split_command
33

4-
import pexpect
54
import pytest
65

76
from code42cli.errors import Code42CLIError
8-
from code42cli.profile import create_profile
9-
from code42cli.profile import delete_profile
7+
from code42cli.main import cli
108
from code42cli.profile import get_profile
11-
from code42cli.profile import switch_default_profile
9+
1210

1311
TEST_PROFILE_NAME = "TEMP-INTEGRATION-TEST"
1412
_LINE_FEED = b"\r\n"
1513
_PASSWORD_PROMPT = b"Password: "
1614
_ENCODING_TYPE = "utf-8"
1715

1816

19-
@contextmanager
20-
def use_temp_profile():
17+
@pytest.fixture(scope="session")
18+
def integration_test_profile(runner):
2119
"""Creates a temporary profile to use for executing integration tests."""
2220
host = os.environ.get("C42_HOST") or "http://127.0.0.1:4200"
2321
username = os.environ.get("C42_USER") or "[email protected]"
2422
password = os.environ.get("C42_PW") or "test_password"
25-
current_profile_name = _get_current_profile_name()
26-
create_profile(TEST_PROFILE_NAME, host, username, True)
27-
switch_default_profile(TEST_PROFILE_NAME)
28-
yield password
29-
delete_profile(TEST_PROFILE_NAME)
30-
31-
# Switch back to the original profile if there was one
32-
if current_profile_name:
33-
switch_default_profile(current_profile_name)
23+
delete_test_profile = split_command(f"profile delete {TEST_PROFILE_NAME} -y")
24+
create_test_profile = split_command(
25+
f"profile create -n {TEST_PROFILE_NAME} -u {username} -s {host} --password {password} -y"
26+
)
27+
runner.invoke(cli, delete_test_profile)
28+
result = runner.invoke(cli, create_test_profile)
29+
if result.exit_code != 0:
30+
pytest.exit(result.output)
31+
yield
32+
runner.invoke(cli, delete_test_profile)
3433

3534

3635
def _get_current_profile_name():
@@ -41,30 +40,9 @@ def _get_current_profile_name():
4140
return None
4241

4342

44-
@pytest.fixture
45-
def command_runner():
46-
def run_command(command):
47-
with use_temp_profile() as pw:
48-
process = pexpect.spawn(command)
49-
response = []
50-
try:
51-
expected = process.expect([_PASSWORD_PROMPT, pexpect.EOF])
52-
if expected == 0:
53-
process.sendline(pw)
54-
process.expect(_LINE_FEED)
55-
output = process.readlines()
56-
response = [_encode_response(line) for line in output]
57-
else:
58-
output = process.before
59-
response = _encode_response(output).splitlines()
60-
except pexpect.TIMEOUT:
61-
process.close()
62-
return process.exitstatus, response
63-
process.close()
64-
return process.exitstatus, response
65-
66-
return run_command
67-
68-
6943
def _encode_response(line, encoding_type=_ENCODING_TYPE):
7044
return line.decode(encoding_type)
45+
46+
47+
def append_profile(command):
48+
return "{} --profile {}".format(command, TEST_PROFILE_NAME)

tests/integration/test_alert_rules.py

+14-19
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,19 @@
11
import pytest
2+
from tests.integration.conftest import append_profile
3+
from tests.integration.util import assert_test_is_successful
24

3-
ALERT_RULES_COMMAND = "code42 alert-rules"
5+
6+
@pytest.mark.integration
7+
def test_alert_rules_list_command_returns_success_return_code(
8+
runner, integration_test_profile
9+
):
10+
command = "alert-rules list"
11+
assert_test_is_successful(runner, append_profile(command))
412

513

614
@pytest.mark.integration
7-
@pytest.mark.parametrize(
8-
"command",
9-
[
10-
"{} list".format(ALERT_RULES_COMMAND),
11-
"{} show test-rule-id".format(ALERT_RULES_COMMAND),
12-
"{} list -f CSV".format(ALERT_RULES_COMMAND),
13-
"{} list -f TABLE".format(ALERT_RULES_COMMAND),
14-
"{} list -f RAW-JSON".format(ALERT_RULES_COMMAND),
15-
"{} list -f JSON".format(ALERT_RULES_COMMAND),
16-
"{} list --format CSV".format(ALERT_RULES_COMMAND),
17-
"{} list --format TABLE".format(ALERT_RULES_COMMAND),
18-
"{} list --format JSON".format(ALERT_RULES_COMMAND),
19-
"{} list --format RAW-JSON".format(ALERT_RULES_COMMAND),
20-
],
21-
)
22-
def test_alert_rules_command_returns_success_return_code(command, command_runner):
23-
return_code, response = command_runner(command)
24-
assert return_code == 0
15+
def test_alert_rules_show_command_returns_success_return_code(
16+
runner, integration_test_profile
17+
):
18+
command = ("alert-rules show test-rule-id",)
19+
assert_test_is_successful(runner, append_profile(command))

tests/integration/test_alerts.py

+34-36
Original file line numberDiff line numberDiff line change
@@ -1,52 +1,50 @@
11
from datetime import datetime
22
from datetime import timedelta
3+
from shlex import split as split_command
34

45
import pytest
6+
from tests.integration.conftest import append_profile
7+
from tests.integration.util import assert_test_is_successful
8+
from tests.integration.util import DataServer
59

10+
from code42cli.main import cli
611

712
begin_date = datetime.utcnow() - timedelta(days=20)
813
end_date = datetime.utcnow() - timedelta(days=10)
914
begin_date_str = begin_date.strftime("%Y-%m-%d")
1015
end_date_str = end_date.strftime("%Y-%m-%d")
1116

12-
ALERT_SEARCH_COMMAND = "code42 alerts search -b {} -e {}".format(
13-
begin_date_str, end_date_str
14-
)
15-
ADVANCED_QUERY = """{"groupClause":"AND", "groups":[{"filterClause":"AND",
16-
"filters":[{"operator":"ON_OR_AFTER", "term":"eventTimestamp", "value":"2020-09-13T00:00:00.000Z"},
17-
{"operator":"ON_OR_BEFORE", "term":"eventTimestamp", "value":"2020-12-07T13:20:15.195Z"}]}],
18-
"srtDir":"asc", "srtKey":"eventId", "pgNum":1, "pgSize":10000}
19-
"""
20-
ALERT_ADVANCED_QUERY_COMMAND = "code42 alerts search --advanced-query '{}'".format(
21-
ADVANCED_QUERY
22-
)
17+
18+
@pytest.mark.integration
19+
def test_alerts_search_command_returns_success_return_code(
20+
runner, integration_test_profile
21+
):
22+
command = "alerts search -b {} -e {}".format(begin_date_str, end_date_str)
23+
assert_test_is_successful(runner, append_profile(command))
2324

2425

2526
@pytest.mark.integration
2627
@pytest.mark.parametrize(
27-
"command",
28-
[
29-
ALERT_SEARCH_COMMAND,
30-
"{} --state OPEN".format(ALERT_SEARCH_COMMAND),
31-
"{} --state RESOLVED".format(ALERT_SEARCH_COMMAND),
32-
"{} --actor [email protected]".format(ALERT_SEARCH_COMMAND),
33-
"{} --rule-name 'File Upload Alert'".format(ALERT_SEARCH_COMMAND),
34-
"{} --rule-id 962a6a1c-54f6-4477-90bd-a08cc74cbf71".format(
35-
ALERT_SEARCH_COMMAND
36-
),
37-
"{} --rule-type FedEndpointExfiltration".format(ALERT_SEARCH_COMMAND),
38-
"{} --description 'Alert on any file upload'".format(ALERT_SEARCH_COMMAND),
39-
"{} --exclude-rule-type 'FedEndpointExfiltration'".format(ALERT_SEARCH_COMMAND),
40-
"{} --exclude-rule-id '962a6a1c-54f6-4477-90bd-a08cc74cbf71'".format(
41-
ALERT_SEARCH_COMMAND
42-
),
43-
"{} --exclude-rule-name 'File Upload Alert'".format(ALERT_SEARCH_COMMAND),
44-
"{} --exclude-actor-contains '[email protected]'".format(ALERT_SEARCH_COMMAND),
45-
"{} --exclude-actor '[email protected]'".format(ALERT_SEARCH_COMMAND),
46-
"{} --actor-contains '[email protected]'".format(ALERT_SEARCH_COMMAND),
47-
ALERT_ADVANCED_QUERY_COMMAND,
48-
],
28+
"protocol", ["TCP", "UDP"],
4929
)
50-
def test_alert_command_returns_success_return_code(command, command_runner):
51-
return_code, response = command_runner(command)
52-
assert return_code == 0
30+
def test_alerts_send_to_returns_success_return_code(
31+
runner, integration_test_profile, protocol
32+
):
33+
command = "alerts send-to localhost:5140 -p {} -b {}".format(
34+
protocol, begin_date_str
35+
)
36+
with DataServer(protocol=protocol):
37+
result = runner.invoke(cli, split_command(append_profile(command)))
38+
assert result.exit_code == 0
39+
40+
41+
def test_alerts_advanced_query_returns_success_return_code(
42+
runner, integration_test_profile
43+
):
44+
ADVANCED_QUERY = """{"groupClause":"AND", "groups":[{"filterClause":"AND",
45+
"filters":[{"operator":"ON_OR_AFTER", "term":"eventTimestamp", "value":"2020-09-13T00:00:00.000Z"},
46+
{"operator":"ON_OR_BEFORE", "term":"eventTimestamp", "value":"2020-12-07T13:20:15.195Z"}]}],
47+
"srtDir":"asc", "srtKey":"eventId", "pgNum":1, "pgSize":10000}
48+
"""
49+
command = "alerts search --advanced-query '{}'".format(ADVANCED_QUERY)
50+
assert_test_is_successful(runner, append_profile(command))

tests/integration/test_auditlogs.py

+34-34
Original file line numberDiff line numberDiff line change
@@ -1,46 +1,46 @@
11
from datetime import datetime
22
from datetime import timedelta
3+
from shlex import split as split_command
34

45
import pytest
6+
from tests.integration.conftest import append_profile
7+
from tests.integration.util import assert_test_is_successful
8+
from tests.integration.util import DataServer
59

6-
SEARCH_COMMAND = "code42 audit-logs search"
7-
BASE_COMMAND = "{} -b".format(SEARCH_COMMAND)
8-
begin_date = datetime.utcnow() - timedelta(days=-10)
10+
from code42cli.main import cli
11+
12+
13+
begin_date = datetime.utcnow() - timedelta(days=2)
914
begin_date_str = begin_date.strftime("%Y-%m-%d %H:%M:%S")
10-
end_date = datetime.utcnow() - timedelta(days=10)
15+
end_date = datetime.utcnow() - timedelta(days=0)
1116
end_date_str = end_date.strftime("%Y-%m-%d %H:%M:%S")
1217

1318

1419
@pytest.mark.integration
1520
@pytest.mark.parametrize(
16-
"command",
17-
[
18-
("{} '{}'".format(BASE_COMMAND, begin_date_str)),
19-
("{} '{}' -e '{}'".format(BASE_COMMAND, begin_date_str, end_date_str)),
20-
("{} '{}' --end '{}'".format(BASE_COMMAND, begin_date_str, end_date_str)),
21-
("{} '{}' --event-type '{}'".format(BASE_COMMAND, begin_date_str, "test")),
22-
("{} '{}' --username '{}'".format(BASE_COMMAND, begin_date_str, "test")),
23-
("{} '{}' --user-id '{}'".format(BASE_COMMAND, begin_date_str, "123")),
24-
("{} '{}' --user-ip '{}'".format(BASE_COMMAND, begin_date_str, "0.0.0.0")),
25-
("{} '{}' --affected-user-id '{}'".format(BASE_COMMAND, begin_date_str, "123")),
26-
(
27-
"{} '{}' --affected-username '{}'".format(
28-
BASE_COMMAND, begin_date_str, "test"
29-
)
30-
),
31-
("{} '{}' -f {}".format(BASE_COMMAND, begin_date_str, "CSV")),
32-
("{} '{}' -f '{}'".format(BASE_COMMAND, begin_date_str, "TABLE")),
33-
("{} '{}' -f '{}'".format(BASE_COMMAND, begin_date_str, "JSON")),
34-
("{} '{}' -f '{}'".format(BASE_COMMAND, begin_date_str, "RAW-JSON")),
35-
("{} '{}' --format {}".format(BASE_COMMAND, begin_date_str, "CSV")),
36-
("{} '{}' --format '{}'".format(BASE_COMMAND, begin_date_str, "TABLE")),
37-
("{} '{}' --format '{}'".format(BASE_COMMAND, begin_date_str, "JSON")),
38-
("{} '{}' --format '{}'".format(BASE_COMMAND, begin_date_str, "RAW-JSON")),
39-
("{} --begin '{}'".format(SEARCH_COMMAND, begin_date_str)),
40-
("{} '{}' -d".format(BASE_COMMAND, begin_date_str)),
41-
("{} '{}' --debug".format(BASE_COMMAND, begin_date_str)),
42-
],
21+
"protocol", ["TCP", "UDP"],
4322
)
44-
def test_auditlogs_search_command_returns_success_return_code(command, command_runner):
45-
return_code, response = command_runner(command)
46-
assert return_code == 0
23+
def test_auditlogs_send_to_command_returns_success_return_code(
24+
runner, integration_test_profile, protocol
25+
):
26+
command = "audit-logs send-to localhost:5140 -p {} -b '{}'".format(
27+
protocol, begin_date_str
28+
)
29+
with DataServer(protocol=protocol):
30+
result = runner.invoke(cli, split_command(append_profile(command)))
31+
assert result.exit_code == 0
32+
33+
34+
@pytest.mark.integration
35+
def test_auditlogs_search_command_with_short_hand_begin_returns_success_return_code(
36+
runner, integration_test_profile
37+
):
38+
command = "audit-logs search -b '{}'".format(begin_date_str)
39+
assert_test_is_successful(runner, append_profile(command))
40+
41+
42+
def test_auditlogs_search_command_with_full_begin_returns_success_return_code(
43+
runner, integration_test_profile,
44+
):
45+
command = "audit-logs search --begin '{}'".format(begin_date_str)
46+
assert_test_is_successful(runner, append_profile(command))

tests/integration/test_cases.py

+7-27
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,11 @@
11
import pytest
2-
from tests.integration import run_command
3-
4-
CASES_COMMAND = "code42 cases"
2+
from tests.integration.conftest import append_profile
3+
from tests.integration.util import assert_test_is_successful
54

65

76
@pytest.mark.integration
8-
@pytest.mark.parametrize(
9-
"command",
10-
[
11-
"{} list".format(CASES_COMMAND),
12-
"{} list -f TABLE".format(CASES_COMMAND),
13-
"{} list -f RAW-JSON".format(CASES_COMMAND),
14-
"{} list -f JSON".format(CASES_COMMAND),
15-
"{} list --format CSV".format(CASES_COMMAND),
16-
"{} list --format TABLE".format(CASES_COMMAND),
17-
"{} list --format JSON".format(CASES_COMMAND),
18-
"{} list --format RAW-JSON".format(CASES_COMMAND),
19-
"{} list --assignee 123".format(CASES_COMMAND),
20-
"{} list --status OPEN".format(CASES_COMMAND),
21-
"{} list --subject 123".format(CASES_COMMAND),
22-
"{} list --begin-create-time 2021-01-01".format(CASES_COMMAND),
23-
"{} list --end-create-time 2021-01-01".format(CASES_COMMAND),
24-
"{} list --begin-update-time 2021-01-01".format(CASES_COMMAND),
25-
"{} list --end-update-time 2021-01-01".format(CASES_COMMAND),
26-
"{} list --name test".format(CASES_COMMAND),
27-
],
28-
)
29-
def test_alert_rules_command_returns_success_return_code(command):
30-
return_code, response = run_command(command)
31-
assert return_code == 0
7+
def test_cases_list_command_returns_success_return_code(
8+
runner, integration_test_profile
9+
):
10+
command = "cases list"
11+
assert_test_is_successful(runner, append_profile(command))

tests/integration/test_legal_hold.py

+14-20
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,18 @@
11
import pytest
2-
3-
LEGAL_HOLD_COMMAND = "code42 legal-hold"
2+
from tests.integration.conftest import append_profile
3+
from tests.integration.util import assert_test_is_successful
44

55

66
@pytest.mark.integration
7-
@pytest.mark.parametrize(
8-
"command",
9-
[
10-
"{} list".format(LEGAL_HOLD_COMMAND),
11-
"{} show 984140047896012577".format(LEGAL_HOLD_COMMAND),
12-
"{} list -f CSV".format(LEGAL_HOLD_COMMAND),
13-
"{} list -f TABLE".format(LEGAL_HOLD_COMMAND),
14-
"{} list -f RAW-JSON".format(LEGAL_HOLD_COMMAND),
15-
"{} list -f JSON".format(LEGAL_HOLD_COMMAND),
16-
"{} list --format CSV".format(LEGAL_HOLD_COMMAND),
17-
"{} list --format TABLE".format(LEGAL_HOLD_COMMAND),
18-
"{} list --format JSON".format(LEGAL_HOLD_COMMAND),
19-
"{} list --format RAW-JSON".format(LEGAL_HOLD_COMMAND),
20-
],
21-
)
22-
def test_alert_rules_command_returns_success_return_code(command, command_runner):
23-
return_code, response = command_runner(command)
24-
assert return_code == 0
7+
def test_legal_hold_list_command_returns_success_return_code(
8+
runner, integration_test_profile
9+
):
10+
command = "legal-hold list"
11+
assert_test_is_successful(runner, append_profile(command))
12+
13+
14+
def test_legal_hold_show_command_returns_success_return_code(
15+
runner, integration_test_profile
16+
):
17+
command = ("legal-hold show 984140047896012577",)
18+
assert_test_is_successful(runner, append_profile(command))

0 commit comments

Comments
 (0)