Extract logic for building the snapshots to improve testability am: f5245ce53d
Original change: https://android-review.googlesource.com/c/platform/packages/modules/common/+/1954695 Change-Id: Ia8be7376929a0cc29074b31562c7e888fce371d5
This commit is contained in:
@@ -195,6 +195,67 @@ class SubprocessRunner:
|
|||||||
*args, check=True, stdout=self.stdout, stderr=self.stderr, **kwargs)
|
*args, check=True, stdout=self.stdout, stderr=self.stderr, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
@dataclasses.dataclass()
|
||||||
|
class SnapshotBuilder:
|
||||||
|
"""Builds sdk snapshots"""
|
||||||
|
|
||||||
|
# Used to run subprocesses for building snapshots.
|
||||||
|
subprocess_runner: SubprocessRunner
|
||||||
|
|
||||||
|
# The OUT_DIR environment variable.
|
||||||
|
out_dir: str
|
||||||
|
|
||||||
|
def get_mainline_sdks_path(self):
|
||||||
|
"""Get the path to the Soong mainline-sdks directory"""
|
||||||
|
return os.path.join(self.out_dir, "soong/mainline-sdks")
|
||||||
|
|
||||||
|
def get_sdk_path(self, sdk_name, sdk_version):
|
||||||
|
"""Get the path to the sdk snapshot zip file produced by soong"""
|
||||||
|
return os.path.join(self.get_mainline_sdks_path(),
|
||||||
|
f"{sdk_name}-{sdk_version}.zip")
|
||||||
|
|
||||||
|
def build_snapshots(self, sdk_versions, modules):
|
||||||
|
# Build the SDKs once for each version.
|
||||||
|
for sdk_version in sdk_versions:
|
||||||
|
# Compute the paths to all the Soong generated sdk snapshot files
|
||||||
|
# required by this script.
|
||||||
|
paths = [
|
||||||
|
self.get_sdk_path(sdk, sdk_version)
|
||||||
|
for module in modules
|
||||||
|
for sdk in module.sdks
|
||||||
|
]
|
||||||
|
|
||||||
|
# TODO(ngeoffray): remove SOONG_ALLOW_MISSING_DEPENDENCIES, but we
|
||||||
|
# currently break without it.
|
||||||
|
#
|
||||||
|
# Set SOONG_SDK_SNAPSHOT_USE_SRCJAR to generate .srcjars inside sdk
|
||||||
|
# zip files as expected by prebuilt drop.
|
||||||
|
extraEnv = {
|
||||||
|
"SOONG_ALLOW_MISSING_DEPENDENCIES": "true",
|
||||||
|
"SOONG_SDK_SNAPSHOT_USE_SRCJAR": "true",
|
||||||
|
"SOONG_SDK_SNAPSHOT_VERSION": sdk_version,
|
||||||
|
}
|
||||||
|
# Unless explicitly specified in the calling environment set
|
||||||
|
# TARGET_BUILD_VARIANT=user.
|
||||||
|
# This MUST be identical to the TARGET_BUILD_VARIANT used to build
|
||||||
|
# the corresponding APEXes otherwise it could result in different
|
||||||
|
# hidden API flags, see http://b/202398851#comment29 for more info.
|
||||||
|
targetBuildVariant = os.environ.get("TARGET_BUILD_VARIANT", "user")
|
||||||
|
cmd = [
|
||||||
|
"build/soong/soong_ui.bash",
|
||||||
|
"--make-mode",
|
||||||
|
"--soong-only",
|
||||||
|
f"TARGET_BUILD_VARIANT={targetBuildVariant}",
|
||||||
|
"TARGET_PRODUCT=mainline_sdk",
|
||||||
|
"MODULE_BUILD_FROM_SOURCE=true",
|
||||||
|
"out/soong/apex/depsinfo/new-allowed-deps.txt.check",
|
||||||
|
] + paths
|
||||||
|
print_command(extraEnv, cmd)
|
||||||
|
env = os.environ.copy()
|
||||||
|
env.update(extraEnv)
|
||||||
|
self.subprocess_runner.run(cmd, env=env)
|
||||||
|
|
||||||
|
|
||||||
@dataclasses.dataclass(frozen=True)
|
@dataclasses.dataclass(frozen=True)
|
||||||
class MainlineModule:
|
class MainlineModule:
|
||||||
"""Represents a mainline module"""
|
"""Represents a mainline module"""
|
||||||
@@ -315,10 +376,10 @@ class SdkDistProducer:
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
# Used to run subprocesses for this.
|
# Used to run subprocesses for this.
|
||||||
subprocess_runner: SubprocessRunner = SubprocessRunner()
|
subprocess_runner: SubprocessRunner
|
||||||
|
|
||||||
# The OUT_DIR environment variable.
|
# Builds sdk snapshots
|
||||||
out_dir: str = "uninitialized-out"
|
snapshot_builder: SnapshotBuilder
|
||||||
|
|
||||||
# The DIST_DIR environment variable.
|
# The DIST_DIR environment variable.
|
||||||
dist_dir: str = "uninitialized-dist"
|
dist_dir: str = "uninitialized-dist"
|
||||||
@@ -327,60 +388,17 @@ class SdkDistProducer:
|
|||||||
# transformed to document where the changes came from.
|
# transformed to document where the changes came from.
|
||||||
script: str = sys.argv[0]
|
script: str = sys.argv[0]
|
||||||
|
|
||||||
def get_sdk_path(self, sdk_name, sdk_version):
|
|
||||||
"""Get the path to the sdk snapshot zip file produced by soong"""
|
|
||||||
return os.path.join(self.out_dir, "soong/mainline-sdks",
|
|
||||||
f"{sdk_name}-{sdk_version}.zip")
|
|
||||||
|
|
||||||
def produce_dist(self, modules):
|
def produce_dist(self, modules):
|
||||||
sdk_versions = SDK_VERSIONS
|
sdk_versions = SDK_VERSIONS
|
||||||
self.build_sdks(sdk_versions, modules)
|
self.build_sdks(sdk_versions, modules)
|
||||||
self.populate_dist(sdk_versions, modules)
|
self.populate_dist(sdk_versions, modules)
|
||||||
|
|
||||||
def build_sdks(self, sdk_versions, modules):
|
def build_sdks(self, sdk_versions, modules):
|
||||||
# Build the SDKs once for each version.
|
self.snapshot_builder.build_snapshots(sdk_versions, modules)
|
||||||
for sdk_version in sdk_versions:
|
|
||||||
# Compute the paths to all the Soong generated sdk snapshot files
|
|
||||||
# required by this script.
|
|
||||||
paths = [
|
|
||||||
self.get_sdk_path(sdk, sdk_version)
|
|
||||||
for module in modules
|
|
||||||
for sdk in module.sdks
|
|
||||||
]
|
|
||||||
|
|
||||||
# TODO(ngeoffray): remove SOONG_ALLOW_MISSING_DEPENDENCIES, but we
|
|
||||||
# currently break without it.
|
|
||||||
#
|
|
||||||
# Set SOONG_SDK_SNAPSHOT_USE_SRCJAR to generate .srcjars inside sdk
|
|
||||||
# zip files as expected by prebuilt drop.
|
|
||||||
extraEnv = {
|
|
||||||
"SOONG_ALLOW_MISSING_DEPENDENCIES": "true",
|
|
||||||
"SOONG_SDK_SNAPSHOT_USE_SRCJAR": "true",
|
|
||||||
"SOONG_SDK_SNAPSHOT_VERSION": sdk_version,
|
|
||||||
}
|
|
||||||
# Unless explicitly specified in the calling environment set
|
|
||||||
# TARGET_BUILD_VARIANT=user.
|
|
||||||
# This MUST be identical to the TARGET_BUILD_VARIANT used to build
|
|
||||||
# the corresponding APEXes otherwise it could result in different
|
|
||||||
# hidden API flags, see http://b/202398851#comment29 for more info.
|
|
||||||
targetBuildVariant = os.environ.get("TARGET_BUILD_VARIANT", "user")
|
|
||||||
cmd = [
|
|
||||||
"build/soong/soong_ui.bash",
|
|
||||||
"--make-mode",
|
|
||||||
"--soong-only",
|
|
||||||
f"TARGET_BUILD_VARIANT={targetBuildVariant}",
|
|
||||||
"TARGET_PRODUCT=mainline_sdk",
|
|
||||||
"MODULE_BUILD_FROM_SOURCE=true",
|
|
||||||
"out/soong/apex/depsinfo/new-allowed-deps.txt.check",
|
|
||||||
] + paths
|
|
||||||
print_command(extraEnv, cmd)
|
|
||||||
env = os.environ.copy()
|
|
||||||
env.update(extraEnv)
|
|
||||||
self.subprocess_runner.run(cmd, env=env)
|
|
||||||
|
|
||||||
def unzip_current_stubs(self, sdk_name, apex_name):
|
def unzip_current_stubs(self, sdk_name, apex_name):
|
||||||
"""Unzips stubs for "current" into {producer.dist_dir}/stubs/{apex}."""
|
"""Unzips stubs for "current" into {producer.dist_dir}/stubs/{apex}."""
|
||||||
sdk_path = self.get_sdk_path(sdk_name, "current")
|
sdk_path = self.snapshot_builder.get_sdk_path(sdk_name, "current")
|
||||||
dest_dir = os.path.join(self.dist_dir, "stubs", apex_name)
|
dest_dir = os.path.join(self.dist_dir, "stubs", apex_name)
|
||||||
print(
|
print(
|
||||||
f"Extracting java_sdk_library files from {sdk_path} to {dest_dir}")
|
f"Extracting java_sdk_library files from {sdk_path} to {dest_dir}")
|
||||||
@@ -420,7 +438,8 @@ class SdkDistProducer:
|
|||||||
|
|
||||||
sdk_dist_dir = os.path.join(sdks_dist_dir, sdk_version,
|
sdk_dist_dir = os.path.join(sdks_dist_dir, sdk_version,
|
||||||
apex, subdir)
|
apex, subdir)
|
||||||
sdk_path = self.get_sdk_path(sdk, sdk_version)
|
sdk_path = self.snapshot_builder.get_sdk_path(
|
||||||
|
sdk, sdk_version)
|
||||||
self.dist_sdk_snapshot_zip(sdk_path, sdk_dist_dir,
|
self.dist_sdk_snapshot_zip(sdk_path, sdk_dist_dir,
|
||||||
module.transformations())
|
module.transformations())
|
||||||
|
|
||||||
@@ -512,11 +531,20 @@ def apply_transformations(producer, tmp_dir, transformations):
|
|||||||
|
|
||||||
|
|
||||||
def create_producer():
|
def create_producer():
|
||||||
return SdkDistProducer(
|
|
||||||
# Variables initialized from environment variables that are set by the
|
# Variables initialized from environment variables that are set by the
|
||||||
# calling mainline_modules_sdks.sh.
|
# calling mainline_modules_sdks.sh.
|
||||||
out_dir=os.environ["OUT_DIR"],
|
out_dir = os.environ["OUT_DIR"]
|
||||||
dist_dir=os.environ["DIST_DIR"],
|
dist_dir = os.environ["DIST_DIR"]
|
||||||
|
|
||||||
|
subprocess_runner = SubprocessRunner()
|
||||||
|
snapshot_builder = SnapshotBuilder(
|
||||||
|
subprocess_runner=subprocess_runner,
|
||||||
|
out_dir=out_dir,
|
||||||
|
)
|
||||||
|
return SdkDistProducer(
|
||||||
|
subprocess_runner=subprocess_runner,
|
||||||
|
snapshot_builder=snapshot_builder,
|
||||||
|
dist_dir=dist_dir,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -14,7 +14,6 @@
|
|||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
"""Unit tests for mainline_modules_sdks.py."""
|
"""Unit tests for mainline_modules_sdks.py."""
|
||||||
|
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
import os
|
import os
|
||||||
import tempfile
|
import tempfile
|
||||||
@@ -24,12 +23,15 @@ import zipfile
|
|||||||
import mainline_modules_sdks as mm
|
import mainline_modules_sdks as mm
|
||||||
|
|
||||||
|
|
||||||
class TestPopulateDist(unittest.TestCase):
|
class FakeSnapshotBuilder(mm.SnapshotBuilder):
|
||||||
|
"""A fake snapshot builder that does not run the build.
|
||||||
|
|
||||||
def create_snapshot_file(self, out_dir, name, version):
|
This skips the whole build process and just creates some fake sdk
|
||||||
sdks_out_dir = Path(out_dir, "soong/mainline-sdks")
|
modules.
|
||||||
sdks_out_dir.mkdir(parents=True, exist_ok=True)
|
"""
|
||||||
zip_file = Path(sdks_out_dir, f"{name}-{version}.zip")
|
|
||||||
|
def create_snapshot_file(self, name, version):
|
||||||
|
zip_file = Path(self.get_sdk_path(name, version))
|
||||||
with zipfile.ZipFile(zip_file, "w") as z:
|
with zipfile.ZipFile(zip_file, "w") as z:
|
||||||
z.writestr("Android.bp", "")
|
z.writestr("Android.bp", "")
|
||||||
if name.endswith("-sdk"):
|
if name.endswith("-sdk"):
|
||||||
@@ -38,6 +40,19 @@ class TestPopulateDist(unittest.TestCase):
|
|||||||
z.writestr("sdk_library/public/lib.jar", "")
|
z.writestr("sdk_library/public/lib.jar", "")
|
||||||
z.writestr("sdk_library/public/api.txt", "")
|
z.writestr("sdk_library/public/api.txt", "")
|
||||||
|
|
||||||
|
def build_snapshots(self, sdk_versions, modules):
|
||||||
|
# Create input file structure.
|
||||||
|
sdks_out_dir = Path(self.get_mainline_sdks_path())
|
||||||
|
sdks_out_dir.mkdir(parents=True, exist_ok=True)
|
||||||
|
# Create a fake sdk zip file for each module.
|
||||||
|
for module in modules:
|
||||||
|
for sdk in module.sdks:
|
||||||
|
for sdk_version in sdk_versions:
|
||||||
|
self.create_snapshot_file(sdk, sdk_version)
|
||||||
|
|
||||||
|
|
||||||
|
class TestProduceDist(unittest.TestCase):
|
||||||
|
|
||||||
def test(self):
|
def test(self):
|
||||||
"""Verify the dist/mainline-sdks directory is populated correctly"""
|
"""Verify the dist/mainline-sdks directory is populated correctly"""
|
||||||
with tempfile.TemporaryDirectory() as tmp_dir:
|
with tempfile.TemporaryDirectory() as tmp_dir:
|
||||||
@@ -51,18 +66,20 @@ class TestPopulateDist(unittest.TestCase):
|
|||||||
mm.MAINLINE_MODULES_BY_APEX["com.android.ipsec"],
|
mm.MAINLINE_MODULES_BY_APEX["com.android.ipsec"],
|
||||||
]
|
]
|
||||||
|
|
||||||
# Create input file structure.
|
subprocess_runner = mm.SubprocessRunner()
|
||||||
for module in modules:
|
|
||||||
for sdk in module.sdks:
|
snapshot_builder = FakeSnapshotBuilder(
|
||||||
self.create_snapshot_file(tmp_out_dir, sdk, "current")
|
subprocess_runner=subprocess_runner,
|
||||||
|
out_dir=tmp_out_dir,
|
||||||
|
)
|
||||||
|
|
||||||
producer = mm.SdkDistProducer(
|
producer = mm.SdkDistProducer(
|
||||||
out_dir=tmp_out_dir,
|
subprocess_runner=subprocess_runner,
|
||||||
|
snapshot_builder=snapshot_builder,
|
||||||
dist_dir=tmp_dist_dir,
|
dist_dir=tmp_dist_dir,
|
||||||
)
|
)
|
||||||
|
|
||||||
sdk_versions = ["current"]
|
producer.produce_dist(modules)
|
||||||
producer.populate_dist(sdk_versions, modules)
|
|
||||||
|
|
||||||
files = []
|
files = []
|
||||||
for abs_dir, _, filenames in os.walk(tmp_dist_dir):
|
for abs_dir, _, filenames in os.walk(tmp_dist_dir):
|
||||||
@@ -114,7 +131,11 @@ def readTestData(relative_path):
|
|||||||
class TestSoongConfigBoilerplateInserter(unittest.TestCase):
|
class TestSoongConfigBoilerplateInserter(unittest.TestCase):
|
||||||
|
|
||||||
def apply_transformations(self, src, transformations, expected):
|
def apply_transformations(self, src, transformations, expected):
|
||||||
producer = mm.SdkDistProducer(script=self._testMethodName)
|
producer = mm.SdkDistProducer(
|
||||||
|
subprocess_runner=None,
|
||||||
|
snapshot_builder=None,
|
||||||
|
script=self._testMethodName,
|
||||||
|
)
|
||||||
|
|
||||||
with tempfile.TemporaryDirectory() as tmp_dir:
|
with tempfile.TemporaryDirectory() as tmp_dir:
|
||||||
path = os.path.join(tmp_dir, "Android.bp")
|
path = os.path.join(tmp_dir, "Android.bp")
|
||||||
|
|||||||
Reference in New Issue
Block a user