blob: 2fc04bf123802d5d3255099a8f0c7affbc86ea0e [file] [log] [blame]
Wei Li340ee8e2022-03-18 17:33:24 -07001#!/usr/bin/env python3
2#
3# Copyright (C) 2022 The Android Open Source Project
4#
5# Licensed under the Apache License, Version 2.0 (the "License");
6# you may not use this file except in compliance with the License.
7# You may obtain a copy of the License at
8#
9# http://www.apache.org/licenses/LICENSE-2.0
10#
11# Unless required by applicable law or agreed to in writing, software
12# distributed under the License is distributed on an "AS IS" BASIS,
13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14# See the License for the specific language governing permissions and
15# limitations under the License.
16
17import hashlib
18import logging
19import os
20import subprocess
21import tempfile
22import unittest
23
24import google.protobuf.text_format as text_format
25import provenance_metadata_pb2
26
27logger = logging.getLogger(__name__)
28
29def run(args, verbose=None, **kwargs):
30 """Creates and returns a subprocess.Popen object.
31
32 Args:
33 args: The command represented as a list of strings.
34 verbose: Whether the commands should be shown. Default to the global
35 verbosity if unspecified.
36 kwargs: Any additional args to be passed to subprocess.Popen(), such as env,
37 stdin, etc. stdout and stderr will default to subprocess.PIPE and
38 subprocess.STDOUT respectively unless caller specifies any of them.
39 universal_newlines will default to True, as most of the users in
40 releasetools expect string output.
41
42 Returns:
43 A subprocess.Popen object.
44 """
45 if 'stdout' not in kwargs and 'stderr' not in kwargs:
46 kwargs['stdout'] = subprocess.PIPE
47 kwargs['stderr'] = subprocess.STDOUT
48 if 'universal_newlines' not in kwargs:
49 kwargs['universal_newlines'] = True
50 if verbose:
51 logger.info(" Running: \"%s\"", " ".join(args))
52 return subprocess.Popen(args, **kwargs)
53
54
55def run_and_check_output(args, verbose=None, **kwargs):
56 """Runs the given command and returns the output.
57
58 Args:
59 args: The command represented as a list of strings.
60 verbose: Whether the commands should be shown. Default to the global
61 verbosity if unspecified.
62 kwargs: Any additional args to be passed to subprocess.Popen(), such as env,
63 stdin, etc. stdout and stderr will default to subprocess.PIPE and
64 subprocess.STDOUT respectively unless caller specifies any of them.
65
66 Returns:
67 The output string.
68
69 Raises:
70 ExternalError: On non-zero exit from the command.
71 """
72 proc = run(args, verbose=verbose, **kwargs)
73 output, _ = proc.communicate()
74 if output is None:
75 output = ""
76 if verbose:
77 logger.info("%s", output.rstrip())
78 if proc.returncode != 0:
79 raise RuntimeError(
80 "Failed to run command '{}' (exit code {}):\n{}".format(
81 args, proc.returncode, output))
82 return output
83
84def run_host_command(args, verbose=None, **kwargs):
85 host_build_top = os.environ.get("ANDROID_BUILD_TOP")
86 if host_build_top:
87 host_command_dir = os.path.join(host_build_top, "out/host/linux-x86/bin")
88 args[0] = os.path.join(host_command_dir, args[0])
89 return run_and_check_output(args, verbose, **kwargs)
90
91def sha256(s):
92 h = hashlib.sha256()
93 h.update(bytearray(s, 'utf-8'))
94 return h.hexdigest()
95
96class ProvenanceMetaDataToolTest(unittest.TestCase):
97
98 def test_gen_provenance_metadata(self):
99 artifact_content = "test artifact"
100 artifact_file = tempfile.mktemp()
101 with open(artifact_file,"wt") as f:
102 f.write(artifact_content)
103 metadata_file = tempfile.mktemp()
104 cmd = ["gen_provenance_metadata"]
105 cmd.extend(["--module_name", "a"])
106 cmd.extend(["--artifact_path", artifact_file])
107 cmd.extend(["--install_path", "b"])
108 cmd.extend(["--metadata_path", metadata_file])
109 output = run_host_command(cmd)
110 self.assertEqual(output, "")
111
112 with open(metadata_file,"rt") as f:
113 data = f.read()
114 provenance_metadata = provenance_metadata_pb2.ProvenanceMetadata()
115 text_format.Parse(data, provenance_metadata)
116 self.assertEqual(provenance_metadata.module_name, "a")
117 self.assertEqual(provenance_metadata.artifact_path, artifact_file)
118 self.assertEqual(provenance_metadata.artifact_install_path, "b")
119 self.assertEqual(provenance_metadata.artifact_sha256, sha256(artifact_content))
120
121 os.remove(artifact_file)
122 os.remove(metadata_file)
123
124if __name__ == '__main__':
125 unittest.main(verbosity=2)