blob: c719efba12b5ef39303601345e6474724fd2c5ad [file] [log] [blame]
# Copyright 2021 The Pigweed Authors
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may not
# use this file except in compliance with the License. You may obtain a copy of
# the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations under
# the License.
"""Tests for pw_build_info's GNU build ID support."""
import subprocess
import tempfile
import unittest
from pathlib import Path
from pw_build_info import build_id
# Since build_id.cc depends on pw_preprocessor, we have to use the in-tree path.
_MODULE_DIR = Path(__file__).parent.parent.resolve()
_MODULE_PY_DIR = Path(__file__).parent.resolve()
_SHA1_BUILD_ID_LENGTH = 20
class TestGnuBuildId(unittest.TestCase):
"""Unit tests for GNU build ID parsing."""
def test_build_id_correctness(self):
"""Tests to ensure GNU build IDs are read/written correctly."""
with tempfile.TemporaryDirectory() as exe_dir:
exe_file = Path(exe_dir) / 'print_build_id.elf'
# Compiles a binary that prints the embedded GNU build id.
cmd = [
'clang++',
'build_id.cc',
_MODULE_PY_DIR / 'print_build_id.cc',
'-Ipublic',
'-I../pw_polyfill/public',
'-I../pw_preprocessor/public',
'-I../pw_span/public',
'-std=c++17',
'-fuse-ld=lld',
'-Wl,-Tadd_build_id_to_default_linker_script.ld',
'-Wl,--build-id=sha1',
'-o',
exe_file,
]
process = subprocess.run(cmd,
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
cwd=_MODULE_DIR)
self.assertEqual(process.returncode, 0,
process.stdout.decode(errors='replace'))
# Run the compiled binary so the printed build ID can be read.
process = subprocess.run([exe_file],
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
cwd=_MODULE_DIR)
self.assertEqual(process.returncode, 0)
with open(exe_file, 'rb') as elf:
expected = build_id.read_build_id_from_section(elf)
self.assertEqual(len(expected), _SHA1_BUILD_ID_LENGTH)
self.assertEqual(process.stdout.decode().rstrip(),
expected.hex())
# Test method that parses using symbol information.
expected = build_id.read_build_id_from_symbol(elf)
self.assertEqual(len(expected), _SHA1_BUILD_ID_LENGTH)
self.assertEqual(process.stdout.decode().rstrip(),
expected.hex())
# Test the user-facing method.
expected = build_id.read_build_id(elf)
self.assertEqual(len(expected), _SHA1_BUILD_ID_LENGTH)
self.assertEqual(process.stdout.decode().rstrip(),
expected.hex())
if __name__ == '__main__':
unittest.main()