Mike Frysinger | f1ba7ad | 2022-09-12 05:42:57 -0400 | [diff] [blame^] | 1 | # Copyright 2021 The ChromiumOS Authors |
George Burgess IV | 757887f | 2021-09-22 15:58:35 -0700 | [diff] [blame] | 2 | # Use of this source code is governed by a BSD-style license that can be |
| 3 | # found in the LICENSE file. |
| 4 | |
| 5 | """Unit tests for xz_auto.py.""" |
| 6 | |
| 7 | import os |
| 8 | from pathlib import Path |
| 9 | import unittest |
| 10 | from unittest import mock |
| 11 | |
| 12 | from chromite.lib import cros_build_lib |
| 13 | from chromite.lib import cros_test_lib |
| 14 | from chromite.lib import osutils |
| 15 | from chromite.scripts import xz_auto |
| 16 | |
| 17 | |
| 18 | DIR = Path(__file__).resolve().parent |
| 19 | |
| 20 | |
| 21 | def FindXzAutoLocation(): |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 22 | """Figures out where the xz_auto binary is.""" |
| 23 | return DIR / "xz_auto" |
George Burgess IV | 757887f | 2021-09-22 15:58:35 -0700 | [diff] [blame] | 24 | |
| 25 | |
| 26 | class XzAutoTests(cros_test_lib.MockTempDirTestCase): |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 27 | """Various tests for xz_auto.""" |
George Burgess IV | 757887f | 2021-09-22 15:58:35 -0700 | [diff] [blame] | 28 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 29 | TEST_FILE_CONTENTS = (b"", b"some random file contents") |
George Burgess IV | d67df46 | 2021-10-27 14:31:33 -0700 | [diff] [blame] | 30 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 31 | def DisablePixzForCurrentTest(self): |
| 32 | """Disables the use of pixz for the current test.""" |
| 33 | # This will be cleaned up by cros_test_lib, so no need to addCleanup. |
| 34 | os.environ[xz_auto.PIXZ_DISABLE_VAR] = "1" |
George Burgess IV | 757887f | 2021-09-22 15:58:35 -0700 | [diff] [blame] | 35 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 36 | def testPixzArgParsingSeemsToWork(self): |
| 37 | """Tests our detection of file names in pixz commandlines.""" |
| 38 | self.assertEqual( |
| 39 | xz_auto.ParsePixzArgs(["to_compress.txt"]), |
| 40 | ([], "to_compress.txt", None), |
| 41 | ) |
| 42 | self.assertEqual( |
| 43 | xz_auto.ParsePixzArgs(["to_compress.txt", "compressed.txt"]), |
| 44 | ([], "to_compress.txt", "compressed.txt"), |
| 45 | ) |
| 46 | self.assertEqual( |
| 47 | xz_auto.ParsePixzArgs( |
| 48 | ["to_compress.txt", "-c", "compressed.txt", "-9"] |
| 49 | ), |
| 50 | (["-c", "-9"], "to_compress.txt", "compressed.txt"), |
| 51 | ) |
| 52 | self.assertEqual( |
| 53 | xz_auto.ParsePixzArgs( |
| 54 | ["-t", "to_compress.txt", "-c", "compressed.txt", "-p", "2"] |
| 55 | ), |
| 56 | (["-t", "-c", "-p", "2"], "to_compress.txt", "compressed.txt"), |
| 57 | ) |
| 58 | self.assertEqual( |
| 59 | xz_auto.ParsePixzArgs( |
| 60 | ["-tcp2", "to_compress.txt", "compressed.txt"] |
| 61 | ), |
| 62 | (["-t", "-c", "-p", "2"], "to_compress.txt", "compressed.txt"), |
| 63 | ) |
George Burgess IV | 757887f | 2021-09-22 15:58:35 -0700 | [diff] [blame] | 64 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 65 | @unittest.skipIf(not xz_auto.HasPixz(), "need pixz for this test") |
| 66 | @mock.patch.object(xz_auto, "Execvp") |
| 67 | def testPixzCommandCreationSelectsPixzIfAvailable(self, execvp_mock): |
| 68 | """Tests that we actually execute pixz when we intend to.""" |
George Burgess IV | 757887f | 2021-09-22 15:58:35 -0700 | [diff] [blame] | 69 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 70 | class ExecvpStopError(Exception): |
| 71 | """Convenient way to halt execution.""" |
George Burgess IV | 757887f | 2021-09-22 15:58:35 -0700 | [diff] [blame] | 72 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 73 | def execvp_side_effect(argv): |
| 74 | """Does testing of our execvp calls.""" |
| 75 | self.assertEqual(argv[0], "pixz") |
| 76 | raise ExecvpStopError() |
George Burgess IV | 757887f | 2021-09-22 15:58:35 -0700 | [diff] [blame] | 77 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 78 | execvp_mock.side_effect = execvp_side_effect |
| 79 | with self.assertRaises(ExecvpStopError): |
| 80 | xz_auto.ExecCompressCommand(stdout=False, argv=[]) |
George Burgess IV | 757887f | 2021-09-22 15:58:35 -0700 | [diff] [blame] | 81 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 82 | with self.assertRaises(ExecvpStopError): |
| 83 | xz_auto.ExecDecompressCommand(stdout=False, argv=[]) |
George Burgess IV | 757887f | 2021-09-22 15:58:35 -0700 | [diff] [blame] | 84 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 85 | def _TestFileCompressionImpl(self, test_empty_file=True): |
| 86 | """Tests that compressing a file with xz_auto WAI.""" |
| 87 | xz_auto_script = str(FindXzAutoLocation()) |
George Burgess IV | d67df46 | 2021-10-27 14:31:33 -0700 | [diff] [blame] | 88 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 89 | test_file_contents = self.TEST_FILE_CONTENTS |
| 90 | if not test_empty_file: |
| 91 | test_file_contents = (x for x in test_file_contents if x) |
George Burgess IV | d67df46 | 2021-10-27 14:31:33 -0700 | [diff] [blame] | 92 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 93 | for file_contents in test_file_contents: |
| 94 | file_location = os.path.join(self.tempdir, "file.txt") |
| 95 | osutils.WriteFile(file_location, file_contents, mode="wb") |
George Burgess IV | d67df46 | 2021-10-27 14:31:33 -0700 | [diff] [blame] | 96 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 97 | cros_build_lib.run( |
| 98 | [ |
| 99 | xz_auto_script, |
| 100 | file_location, |
| 101 | ], |
| 102 | ) |
George Burgess IV | 757887f | 2021-09-22 15:58:35 -0700 | [diff] [blame] | 103 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 104 | xz_location = file_location + ".xz" |
| 105 | self.assertExists(xz_location) |
| 106 | self.assertNotExists(file_location) |
| 107 | cros_build_lib.run( |
| 108 | [ |
| 109 | xz_auto_script, |
| 110 | "--decompress", |
| 111 | xz_location, |
| 112 | ] |
| 113 | ) |
| 114 | self.assertNotExists(xz_location) |
| 115 | self.assertExists(file_location) |
| 116 | self.assertEqual( |
| 117 | osutils.ReadFile(file_location, mode="rb"), |
| 118 | file_contents, |
| 119 | ) |
George Burgess IV | 757887f | 2021-09-22 15:58:35 -0700 | [diff] [blame] | 120 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 121 | def _TestStdoutCompressionImpl(self): |
| 122 | """Tests that compressing stdstreams with xz_auto WAI.""" |
| 123 | xz_auto_script = str(FindXzAutoLocation()) |
| 124 | for file_contents in self.TEST_FILE_CONTENTS: |
| 125 | run_result = cros_build_lib.run( |
| 126 | [ |
| 127 | xz_auto_script, |
| 128 | "-c", |
| 129 | ], |
| 130 | capture_output=True, |
| 131 | input=file_contents, |
| 132 | ) |
George Burgess IV | 757887f | 2021-09-22 15:58:35 -0700 | [diff] [blame] | 133 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 134 | compressed_file = run_result.stdout |
| 135 | self.assertNotEqual(compressed_file, file_contents) |
George Burgess IV | 757887f | 2021-09-22 15:58:35 -0700 | [diff] [blame] | 136 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 137 | run_result = cros_build_lib.run( |
| 138 | [ |
| 139 | xz_auto_script, |
| 140 | "--decompress", |
| 141 | "-c", |
| 142 | ], |
| 143 | input=compressed_file, |
| 144 | capture_output=True, |
| 145 | ) |
| 146 | uncompressed_file = run_result.stdout |
| 147 | self.assertEqual(file_contents, uncompressed_file) |
George Burgess IV | 757887f | 2021-09-22 15:58:35 -0700 | [diff] [blame] | 148 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 149 | def _TestStdoutCompressionFromFileImpl(self): |
| 150 | """Tests that compression of a file & outputting to stdout works. |
George Burgess IV | 757887f | 2021-09-22 15:58:35 -0700 | [diff] [blame] | 151 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 152 | Pixz has some semi-weird behavior here (b/202735786). |
| 153 | """ |
| 154 | xz_auto_script = str(FindXzAutoLocation()) |
| 155 | for file_contents in self.TEST_FILE_CONTENTS: |
| 156 | file_location = os.path.join(self.tempdir, "file.txt") |
| 157 | osutils.WriteFile(file_location, file_contents, mode="wb") |
George Burgess IV | 757887f | 2021-09-22 15:58:35 -0700 | [diff] [blame] | 158 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 159 | run_result = cros_build_lib.run( |
| 160 | [ |
| 161 | xz_auto_script, |
| 162 | "-c", |
| 163 | file_location, |
| 164 | ], |
| 165 | capture_output=True, |
| 166 | ) |
George Burgess IV | 757887f | 2021-09-22 15:58:35 -0700 | [diff] [blame] | 167 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 168 | compressed_file = run_result.stdout |
| 169 | self.assertExists(file_location) |
| 170 | self.assertNotEqual(compressed_file, file_contents) |
George Burgess IV | 757887f | 2021-09-22 15:58:35 -0700 | [diff] [blame] | 171 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 172 | run_result = cros_build_lib.run( |
| 173 | [ |
| 174 | xz_auto_script, |
| 175 | "--decompress", |
| 176 | "-c", |
| 177 | ], |
| 178 | capture_output=True, |
| 179 | input=compressed_file, |
| 180 | ) |
| 181 | uncompressed_file = run_result.stdout |
| 182 | self.assertEqual(file_contents, uncompressed_file) |
George Burgess IV | 757887f | 2021-09-22 15:58:35 -0700 | [diff] [blame] | 183 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 184 | @unittest.skipIf(not xz_auto.HasPixz(), "need pixz for this test") |
| 185 | def testFileCompressionWithPixzWorks(self): |
| 186 | """Tests that compressing a file with pixz WAI.""" |
| 187 | self._TestFileCompressionImpl() |
George Burgess IV | d67df46 | 2021-10-27 14:31:33 -0700 | [diff] [blame] | 188 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 189 | # We fall back to `xz` with small files. Make sure we actually cover the |
| 190 | # pixz case, too. We disable testing of empty inputs, since pixz breaks |
| 191 | # with those. |
| 192 | # |
| 193 | # cros_test_lib will clean this var up at the end of the test. |
| 194 | os.environ[xz_auto.XZ_DISABLE_VAR] = "1" |
| 195 | self._TestFileCompressionImpl(test_empty_file=False) |
George Burgess IV | 757887f | 2021-09-22 15:58:35 -0700 | [diff] [blame] | 196 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 197 | @unittest.skipIf(not xz_auto.HasPixz(), "need pixz for this test") |
| 198 | def testStdoutCompressionWithPixzWorks(self): |
| 199 | """Tests that compressing `stdout` with pixz WAI.""" |
| 200 | self._TestStdoutCompressionImpl() |
George Burgess IV | 757887f | 2021-09-22 15:58:35 -0700 | [diff] [blame] | 201 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 202 | @unittest.skipIf(not xz_auto.HasPixz(), "need pixz for this test") |
| 203 | def testStdoutCompressionFromFileWithPixzWorks(self): |
| 204 | """Tests that compressing from a file to stdout with pixz WAI.""" |
| 205 | self._TestStdoutCompressionFromFileImpl() |
George Burgess IV | 757887f | 2021-09-22 15:58:35 -0700 | [diff] [blame] | 206 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 207 | def testFileCompressionWithXzWorks(self): |
| 208 | """Tests that compressing a file with pixz WAI.""" |
| 209 | self.DisablePixzForCurrentTest() |
| 210 | self._TestFileCompressionImpl() |
George Burgess IV | 757887f | 2021-09-22 15:58:35 -0700 | [diff] [blame] | 211 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 212 | def testStdoutCompressionWithXzWorks(self): |
| 213 | """Tests that compressing `stdout` with pixz WAI.""" |
| 214 | self.DisablePixzForCurrentTest() |
| 215 | self._TestStdoutCompressionImpl() |
| 216 | |
| 217 | def testStdoutCompressionFromFileWithXzWorks(self): |
| 218 | """Tests that compressing from a file to stdout WAI.""" |
| 219 | self.DisablePixzForCurrentTest() |
| 220 | self._TestStdoutCompressionFromFileImpl() |