1# 2# Copyright (C) 2021 The Android Open Source Project 3# 4# Licensed under the Apache License, Version 2.0 (the "License"); 5# you may not use this file except in compliance with the License. 6# You may obtain a copy of the License at 7# 8# http://www.apache.org/licenses/LICENSE-2.0 9# 10# Unless required by applicable law or agreed to in writing, software 11# distributed under the License is distributed on an "AS IS" BASIS, 12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13# See the License for the specific language governing permissions and 14# limitations under the License. 15# 16"""Tests for Soong APIs.""" 17import contextlib 18import os 19from pathlib import Path 20import tempfile 21import unittest 22import unittest.mock 23 24from .soong import Soong 25 26 27if "ANDROID_BUILD_TOP" not in os.environ: 28 raise RuntimeError( 29 "Cannot run Soong tests without ANDROID_BUILD_TOP defined. Run lunch." 30 ) 31 32 33ANDROID_BUILD_TOP = Path(os.environ["ANDROID_BUILD_TOP"]).resolve() 34 35 36class SoongTest(unittest.TestCase): 37 """Tests for the Soong executor.""" 38 39 out_dir: Path 40 41 def setUp(self) -> None: 42 with contextlib.ExitStack() as stack: 43 self.out_dir = Path(stack.enter_context(tempfile.TemporaryDirectory())) 44 self.addCleanup(stack.pop_all().close) 45 46 def test_finds_soong_ui(self) -> None: 47 """Tests that soong_ui.bash is found correctly.""" 48 soong = Soong(ANDROID_BUILD_TOP, self.out_dir) 49 self.assertTrue(soong.soong_ui_path.exists()) 50 self.assertEqual("soong_ui.bash", soong.soong_ui_path.name) 51 52 def test_get_build_var(self) -> None: 53 """Tests that we can read build variables from Soong.""" 54 soong = Soong(ANDROID_BUILD_TOP, self.out_dir) 55 old_product = os.environ["TARGET_PRODUCT"] 56 try: 57 # Clear the lunched target out of the test environment for a 58 # consistent result. 59 del os.environ["TARGET_PRODUCT"] 60 self.assertEqual("generic", soong.get_make_var("TARGET_DEVICE")) 61 finally: 62 os.environ["TARGET_PRODUCT"] = old_product 63 64 def test_clean(self) -> None: 65 """Tests that clean works.""" 66 soong = Soong(ANDROID_BUILD_TOP, self.out_dir) 67 self.assertTrue(self.out_dir.exists()) 68 soong.clean() 69 self.assertFalse(self.out_dir.exists()) 70 soong.clean() 71 self.assertFalse(self.out_dir.exists()) 72 73 def test_build(self) -> None: 74 """Tests that build invokes the correct command. 75 76 Does not actually test a build, as there aren't any good options for short 77 builds in the tree, so instead tests that soong_ui is called the way we expect 78 it to be. 79 """ 80 soong = Soong(ANDROID_BUILD_TOP, self.out_dir) 81 with unittest.mock.patch.object(soong, "soong_ui") as soong_ui: 82 soong.build(["foo"]) 83 soong_ui.assert_called_with( 84 ["--make-mode", "--soong-only", "foo"], env=None 85 ) 86 87 def test_build_creates_out_dir(self) -> None: 88 """Tests that build creates the out directory if necessary.""" 89 soong = Soong(ANDROID_BUILD_TOP, self.out_dir) 90 soong.clean() 91 with unittest.mock.patch.object(soong, "soong_ui"): 92 soong.build([]) 93 self.assertTrue(self.out_dir.exists()) 94