mirror of
https://github.com/mvt-project/mvt.git
synced 2026-09-11 04:08:55 +02:00
Keep the test suite out of the user's MVT folders (#923)
The tests read the settings file of whoever runs them, and importing mvt.common.config writes it back. On a machine whose config.yaml sets NETWORK_ACCESS_ALLOWED to false, the plugin update and URL batch tests fail before their mocked requests are reached, and every Command run in the suite parses the indicators downloaded on that machine, which made the suite take minutes instead of seconds. MVT_CONFIG_FOLDER and MVT_DATA_FOLDER in the environment now relocate the settings file and the downloaded indicators with their update-check state. The test conftest points both at a throwaway folder before any mvt module is imported, and removes it at exit. Subprocesses started by the tests inherit the variables; the isolated interpreter helper already gives them a temporary home. On the machine that prompted this the suite goes from 6 failures in six minutes to none in seven seconds, and config.yaml is left alone.
This commit is contained in:
@@ -12,7 +12,9 @@ from pydantic_settings import (
|
||||
YamlConfigSettingsSource,
|
||||
)
|
||||
|
||||
MVT_CONFIG_FOLDER = user_config_dir("mvt")
|
||||
# MVT_CONFIG_FOLDER in the environment relocates the settings file, so that
|
||||
# a test run or a scripted install never touches the user's own.
|
||||
MVT_CONFIG_FOLDER = os.environ.get("MVT_CONFIG_FOLDER") or user_config_dir("mvt")
|
||||
MVT_CONFIG_PATH = os.path.join(MVT_CONFIG_FOLDER, "config.yaml")
|
||||
|
||||
|
||||
|
||||
@@ -18,7 +18,9 @@ from appdirs import user_data_dir
|
||||
from .config import settings
|
||||
from .url import URL
|
||||
|
||||
MVT_DATA_FOLDER = user_data_dir("mvt")
|
||||
# MVT_DATA_FOLDER in the environment relocates the downloaded indicators and
|
||||
# the update-check state kept next to them.
|
||||
MVT_DATA_FOLDER = os.environ.get("MVT_DATA_FOLDER") or user_data_dir("mvt")
|
||||
MVT_INDICATORS_FOLDER = os.path.join(MVT_DATA_FOLDER, "indicators")
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
@@ -71,7 +73,9 @@ class Indicators:
|
||||
if os.path.isfile(path) and path.lower().endswith(".stix2"):
|
||||
self.parse_stix2(path)
|
||||
elif os.path.isdir(path):
|
||||
for file in glob.glob(os.path.join(path, "**", "*.stix2"), recursive=True):
|
||||
for file in glob.glob(
|
||||
os.path.join(path, "**", "*.stix2"), recursive=True
|
||||
):
|
||||
self.parse_stix2(file)
|
||||
else:
|
||||
self.log.error(
|
||||
@@ -518,9 +522,7 @@ class Indicators:
|
||||
the original URL order.
|
||||
"""
|
||||
batches = [list(urls) if urls else [] for urls in url_batches]
|
||||
unique_urls = list(
|
||||
dict.fromkeys(url for urls in batches for url in urls)
|
||||
)
|
||||
unique_urls = list(dict.fromkeys(url for urls in batches for url in urls))
|
||||
|
||||
if not unique_urls:
|
||||
return [None] * len(batches)
|
||||
|
||||
+20
-7
@@ -3,20 +3,26 @@
|
||||
# Use of this software is governed by the MVT License 1.1 that can be found at
|
||||
# https://license.mvt.re/1.1/
|
||||
|
||||
import atexit
|
||||
import logging
|
||||
import os
|
||||
import shutil
|
||||
import tempfile
|
||||
|
||||
import pytest
|
||||
|
||||
from mvt.common.cli_plugins import (
|
||||
MVT_ANDROID_CUSTOM_COMMANDS_ENV,
|
||||
MVT_CUSTOM_COMMANDS_ENV,
|
||||
MVT_IOS_CUSTOM_COMMANDS_ENV,
|
||||
)
|
||||
from mvt.common.indicators import Indicators
|
||||
|
||||
from .artifacts.generate_stix import generate_test_stix_file
|
||||
|
||||
# The suite must neither read nor write the developer's own MVT settings,
|
||||
# downloaded indicators or update-check state, and mvt.common.config saves
|
||||
# the settings file as soon as it is imported. Both folders are redirected
|
||||
# before any mvt module is imported, which is why this file imports none at
|
||||
# the top; the subprocesses the tests start inherit the variables.
|
||||
MVT_TEST_HOME = tempfile.mkdtemp(prefix="mvt-tests-")
|
||||
atexit.register(shutil.rmtree, MVT_TEST_HOME, ignore_errors=True)
|
||||
os.environ["MVT_CONFIG_FOLDER"] = os.path.join(MVT_TEST_HOME, "config")
|
||||
os.environ["MVT_DATA_FOLDER"] = os.path.join(MVT_TEST_HOME, "data")
|
||||
|
||||
|
||||
@pytest.fixture(scope="session", autouse=True)
|
||||
def indicator_file(request, tmp_path_factory):
|
||||
@@ -47,6 +53,8 @@ def indicators_factory(indicator_file):
|
||||
android_property_names=[],
|
||||
files_sha256=[],
|
||||
):
|
||||
from mvt.common.indicators import Indicators
|
||||
|
||||
ind = Indicators(log=logging.getLogger())
|
||||
ind.parse_stix2(indicator_file)
|
||||
|
||||
@@ -77,6 +85,11 @@ def restore_cli_commands(monkeypatch):
|
||||
"""
|
||||
from mvt.android.cli import cli as android_cli
|
||||
from mvt.cli import cli as neutral_cli
|
||||
from mvt.common.cli_plugins import (
|
||||
MVT_ANDROID_CUSTOM_COMMANDS_ENV,
|
||||
MVT_CUSTOM_COMMANDS_ENV,
|
||||
MVT_IOS_CUSTOM_COMMANDS_ENV,
|
||||
)
|
||||
from mvt.ios.cli import cli as ios_cli
|
||||
|
||||
groups = (neutral_cli, ios_cli, android_cli)
|
||||
|
||||
Reference in New Issue
Block a user