Skip to content

Commit

Permalink
Rewrite test_base.py to use per-test setup instead of per-class (#8621
Browse files Browse the repository at this point in the history
)

Implements #6320 and, by extension, should fix #6282.
  • Loading branch information
Eric-Arellano authored Nov 20, 2019
1 parent 9459eca commit 998ffbb
Show file tree
Hide file tree
Showing 6 changed files with 71 additions and 45 deletions.
4 changes: 2 additions & 2 deletions src/python/pants/testutil/engine/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -163,8 +163,8 @@ def test_foo(self):


def remove_locations_from_traceback(trace):
location_pattern = re.compile('"/.*", line \d+')
address_pattern = re.compile('0x[0-9a-f]+')
location_pattern = re.compile(r'"/.*", line \d+')
address_pattern = re.compile(r'0x[0-9a-f]+')
new_trace = location_pattern.sub('LOCATION-INFO', trace)
new_trace = address_pattern.sub('0xEEEEEEEEE', new_trace)
return new_trace
Expand Down
45 changes: 20 additions & 25 deletions src/python/pants/testutil/test_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -346,21 +346,19 @@ def _reset_engine(self):
self._build_graph.reset()
self._scheduler.invalidate_all_files()

@classmethod
def aggressively_reset_scheduler(cls):
cls._scheduler = None
if cls._local_store_dir is not None:
safe_rmtree(cls._local_store_dir)
def aggressively_reset_scheduler(self):
self._scheduler = None
if self._local_store_dir is not None:
safe_rmtree(self._local_store_dir)

@classmethod
@contextmanager
def isolated_local_store(cls):
cls.aggressively_reset_scheduler()
cls._init_engine()
def isolated_local_store(self):
self.aggressively_reset_scheduler()
self._init_engine()
try:
yield
finally:
cls.aggressively_reset_scheduler()
self.aggressively_reset_scheduler()

@property
def build_root(self):
Expand All @@ -370,38 +368,35 @@ def build_root(self):
def pants_workdir(self):
return self._pants_workdir()

@classmethod
@memoized_method
def _build_root(cls):
def _build_root(self):
return os.path.realpath(mkdtemp(suffix='_BUILD_ROOT'))

@classmethod
@memoized_method
def _pants_workdir(cls):
return os.path.join(cls._build_root(), '.pants.d')
def _pants_workdir(self):
return os.path.join(self._build_root(), '.pants.d')

@classmethod
def _init_engine(cls):
if cls._scheduler is not None:
def _init_engine(self):
if self._scheduler is not None:
return

cls._local_store_dir = os.path.realpath(safe_mkdtemp())
safe_mkdir(cls._local_store_dir)
self._local_store_dir = os.path.realpath(safe_mkdtemp())
safe_mkdir(self._local_store_dir)

# NB: This uses the long form of initialization because it needs to directly specify
# `cls.alias_groups` rather than having them be provided by bootstrap options.
graph_session = EngineInitializer.setup_legacy_graph_extended(
pants_ignore_patterns=None,
local_store_dir=cls._local_store_dir,
local_store_dir=self._local_store_dir,
build_file_imports_behavior='allow',
native=init_native(),
options_bootstrapper=OptionsBootstrapper.create(args=['--pants-config-files=[]']),
build_configuration=cls.build_config(),
build_configuration=self.build_config(),
build_ignore_patterns=None,
).new_session(zipkin_trace_v2=False, build_id="buildid_for_test")
cls._scheduler = graph_session.scheduler_session
cls._build_graph, cls._address_mapper = graph_session.create_build_graph(
TargetRoots([]), cls._build_root()
self._scheduler = graph_session.scheduler_session
self._build_graph, self._address_mapper = graph_session.create_build_graph(
TargetRoots([]), self._build_root()
)

@property
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
from pants.build_graph.target import Target
from pants.java.jar.jar_dependency import JarDependency
from pants.testutil.task_test_base import ConsoleTaskTestBase
from pants.util.dirutil import safe_mkdir, safe_mkdtemp, safe_open
from pants.util.memo import memoized_classproperty


class CheckPublishedDepsTest(ConsoleTaskTestBase):
Expand All @@ -32,16 +34,22 @@ def alias_groups(cls):
'jar': JarDependency,
'scala_artifact': ScalaArtifact,
'scala_jar': ScalaJarDependency,
'repo': Repository(name='repo',
url='http://www.www.com',
push_db_basedir=os.path.join(cls._build_root(), 'repo')),
}
},
context_aware_object_factories={
'repo': lambda _: Repository(
name='repo', url='http://www.www.com', push_db_basedir=cls.push_db_basedir
),
},
)

@classmethod
def task_type(cls):
return CheckPublishedDeps

@memoized_classproperty
def push_db_basedir(cls):
return safe_mkdtemp()

def assert_console_output(self, *args, **kwargs):
# Ensure that JarPublish's repos option is set, as CheckPublishedDeps consults it.
self.set_options_for_scope('publish.jar', repos={})
Expand All @@ -50,13 +58,19 @@ def assert_console_output(self, *args, **kwargs):
def setUp(self):
super().setUp()

self.create_file('repo/org.name/lib1/publish.properties', dedent("""
safe_mkdir(self.push_db_basedir, clean=True)

def write_db_file(relpath, contents):
with safe_open(os.path.join(self.push_db_basedir, relpath), 'w') as fp:
fp.write(contents)

write_db_file('org.name/lib1/publish.properties', dedent("""
revision.major.org.name%lib1=2
revision.minor.org.name%lib1=0
revision.patch.org.name%lib1=0
revision.sha.org.name%lib1=12345
"""))
self.create_file('repo/org.name/lib2/publish.properties', dedent("""
write_db_file('org.name/lib2/publish.properties', dedent("""
revision.major.org.name%lib2=2
revision.minor.org.name%lib2=0
revision.patch.org.name%lib2=0
Expand Down
22 changes: 15 additions & 7 deletions tests/python/pants_test/backend/jvm/tasks/test_jar_publish.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
# Copyright 2014 Pants project contributors (see CONTRIBUTORS.md).
# Licensed under the Apache License, Version 2.0 (see LICENSE).

import os
import unittest
from unittest.mock import Mock

Expand All @@ -17,7 +16,8 @@
from pants.scm.scm import Scm
from pants.testutil.jvm.nailgun_task_test_base import NailgunTaskTestBase
from pants.util.contextutil import temporary_dir
from pants.util.dirutil import safe_mkdir, safe_walk
from pants.util.dirutil import safe_mkdir, safe_mkdtemp, safe_walk
from pants.util.memo import memoized_classproperty


class JarPublishTest(NailgunTaskTestBase):
Expand All @@ -34,9 +34,6 @@ def test_smoke_publish(self):

@classmethod
def alias_groups(cls):
cls.push_db_basedir = os.path.join(cls._build_root(), "pushdb")
safe_mkdir(cls.push_db_basedir)

return BuildFileAliases(
targets={
'jar_library': JarLibrary,
Expand All @@ -46,11 +43,22 @@ def alias_groups(cls):
objects={
'artifact': Artifact,
'scala_artifact': ScalaArtifact,
'internal': Repository(name='internal', url='http://example.com',
push_db_basedir=cls.push_db_basedir),
},
context_aware_object_factories={
'internal': lambda _: Repository(
name='internal', url='http://example.com', push_db_basedir=cls.push_db_basedir
),
},
)

@memoized_classproperty
def push_db_basedir(cls):
return safe_mkdtemp()

def setUp(self):
super().setUp()
safe_mkdir(self.push_db_basedir, clean=True)

def _prepare_for_publishing(self, with_alias=False):
targets = []
nail_target = self._create_nail_target()
Expand Down
1 change: 1 addition & 0 deletions tests/python/pants_test/init/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ python_tests(
'src/python/pants/subsystem',
'src/python/pants/util:contextutil',
'src/python/pants/util:dirutil',
'src/python/pants/testutil/engine:util',
'src/python/pants/testutil/subsystem',
'tests/python/pants_test:interpreter_selection_utils',
'src/python/pants/testutil:test_base',
Expand Down
18 changes: 13 additions & 5 deletions tests/python/pants_test/init/test_logging.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,25 @@
from pathlib import Path

from pants.init.logging import get_numeric_level, setup_logging
from pants.testutil.engine.util import init_native
from pants.testutil.test_base import TestBase
from pants.util.contextutil import temporary_dir


class LoggingTest(TestBase):

def post_scheduler_init(self):
self.native = self.scheduler._scheduler._native
# Initialize it with the least verbose level.
# Individual loggers will increase verbosity as needed.
self.native.init_rust_logging(get_numeric_level("ERROR"), False)
@classmethod
def setUpClass(cls) -> None:
super().setUpClass()
# NB: We must set this up at the class level, rather than per-test level, because
# `init_rust_logging` must never be called more than once. The Rust logger is global and static,
# and initializing it twice in the same test class results in a SIGABRT.
init_native().init_rust_logging(
# We set the level to the least verbose possible, as individual tests will increase the
# verbosity as necessary.
level=get_numeric_level("ERROR"),
log_show_rust_3rdparty=False,
)

@contextmanager
def logger(self, level):
Expand Down

0 comments on commit 998ffbb

Please sign in to comment.