1*61c4878aSAndroid Build Coastguard Worker#!/usr/bin/env python3 2*61c4878aSAndroid Build Coastguard Worker# Copyright 2020 The Pigweed Authors 3*61c4878aSAndroid Build Coastguard Worker# 4*61c4878aSAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License"); you may not 5*61c4878aSAndroid Build Coastguard Worker# use this file except in compliance with the License. You may obtain a copy of 6*61c4878aSAndroid Build Coastguard Worker# the License at 7*61c4878aSAndroid Build Coastguard Worker# 8*61c4878aSAndroid Build Coastguard Worker# https://www.apache.org/licenses/LICENSE-2.0 9*61c4878aSAndroid Build Coastguard Worker# 10*61c4878aSAndroid Build Coastguard Worker# Unless required by applicable law or agreed to in writing, software 11*61c4878aSAndroid Build Coastguard Worker# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12*61c4878aSAndroid Build Coastguard Worker# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13*61c4878aSAndroid Build Coastguard Worker# License for the specific language governing permissions and limitations under 14*61c4878aSAndroid Build Coastguard Worker# the License. 15*61c4878aSAndroid Build Coastguard Worker"""Tests for the database module.""" 16*61c4878aSAndroid Build Coastguard Worker 17*61c4878aSAndroid Build Coastguard Workerimport json 18*61c4878aSAndroid Build Coastguard Workerimport io 19*61c4878aSAndroid Build Coastguard Workerimport os 20*61c4878aSAndroid Build Coastguard Workerfrom pathlib import Path 21*61c4878aSAndroid Build Coastguard Workerimport shutil 22*61c4878aSAndroid Build Coastguard Workerimport stat 23*61c4878aSAndroid Build Coastguard Workerimport subprocess 24*61c4878aSAndroid Build Coastguard Workerimport sys 25*61c4878aSAndroid Build Coastguard Workerimport tempfile 26*61c4878aSAndroid Build Coastguard Workerimport unittest 27*61c4878aSAndroid Build Coastguard Workerfrom unittest import mock 28*61c4878aSAndroid Build Coastguard Worker 29*61c4878aSAndroid Build Coastguard Workerfrom pw_tokenizer import database 30*61c4878aSAndroid Build Coastguard Worker 31*61c4878aSAndroid Build Coastguard Worker# This is an ELF file with only the pw_tokenizer sections. It was created 32*61c4878aSAndroid Build Coastguard Worker# from a tokenize_test binary built for the STM32F429i Discovery board. The 33*61c4878aSAndroid Build Coastguard Worker# pw_tokenizer sections were extracted with this command: 34*61c4878aSAndroid Build Coastguard Worker# 35*61c4878aSAndroid Build Coastguard Worker# arm-none-eabi-objcopy -S --only-section ".pw_tokenize*" <ELF> <OUTPUT> 36*61c4878aSAndroid Build Coastguard Worker# 37*61c4878aSAndroid Build Coastguard WorkerTOKENIZED_ENTRIES_ELF = Path(__file__).with_name( 38*61c4878aSAndroid Build Coastguard Worker 'example_binary_with_tokenized_strings.elf' 39*61c4878aSAndroid Build Coastguard Worker) 40*61c4878aSAndroid Build Coastguard Worker 41*61c4878aSAndroid Build Coastguard WorkerCSV_DEFAULT_DOMAIN = '''\ 42*61c4878aSAndroid Build Coastguard Worker00000000, ,"","" 43*61c4878aSAndroid Build Coastguard Worker141c35d5, ,"","The answer: ""%s""" 44*61c4878aSAndroid Build Coastguard Worker29aef586, ,"","1234" 45*61c4878aSAndroid Build Coastguard Worker2b78825f, ,"","[:-)" 46*61c4878aSAndroid Build Coastguard Worker2e668cd6, ,"","Jello, world!" 47*61c4878aSAndroid Build Coastguard Worker31631781, ,"","%d" 48*61c4878aSAndroid Build Coastguard Worker61fd1e26, ,"","%ld" 49*61c4878aSAndroid Build Coastguard Worker68ab92da, ,"","%s there are %x (%.2f) of them%c" 50*61c4878aSAndroid Build Coastguard Worker7b940e2a, ,"","Hello %s! %hd %e" 51*61c4878aSAndroid Build Coastguard Worker7da55d52, ,"",">:-[]" 52*61c4878aSAndroid Build Coastguard Worker7f35a9a5, ,"","TestName" 53*61c4878aSAndroid Build Coastguard Worker851beeb6, ,"","%u %d" 54*61c4878aSAndroid Build Coastguard Worker881436a0, ,"","The answer is: %s" 55*61c4878aSAndroid Build Coastguard Worker88808930, ,"","%u%d%02x%X%hu%hhd%d%ld%lu%lld%llu%c%c%c" 56*61c4878aSAndroid Build Coastguard Worker92723f44, ,"","???" 57*61c4878aSAndroid Build Coastguard Workera09d6698, ,"","won-won-won-wonderful" 58*61c4878aSAndroid Build Coastguard Workeraa9ffa66, ,"","void pw::tokenizer::{anonymous}::TestName()" 59*61c4878aSAndroid Build Coastguard Workerad002c97, ,"","%llx" 60*61c4878aSAndroid Build Coastguard Workerb3653e13, ,"","Jello!" 61*61c4878aSAndroid Build Coastguard Workercc6d3131, ,"","Jello?" 62*61c4878aSAndroid Build Coastguard Workere13b0f94, ,"","%llu" 63*61c4878aSAndroid Build Coastguard Workere65aefef, ,"","Won't fit : %s%d" 64*61c4878aSAndroid Build Coastguard Worker''' 65*61c4878aSAndroid Build Coastguard Worker 66*61c4878aSAndroid Build Coastguard WorkerCSV_TEST_DOMAIN = """\ 67*61c4878aSAndroid Build Coastguard Worker17fa86d3, ,"TEST_DOMAIN","hello" 68*61c4878aSAndroid Build Coastguard Worker18c5017c, ,"TEST_DOMAIN","yes" 69*61c4878aSAndroid Build Coastguard Worker59b2701c, ,"TEST_DOMAIN","The answer was: %s" 70*61c4878aSAndroid Build Coastguard Worker881436a0, ,"TEST_DOMAIN","The answer is: %s" 71*61c4878aSAndroid Build Coastguard Workerd18ada0f, ,"TEST_DOMAIN","something" 72*61c4878aSAndroid Build Coastguard Worker""" 73*61c4878aSAndroid Build Coastguard Worker 74*61c4878aSAndroid Build Coastguard WorkerCSV_ALL_DOMAINS = '''\ 75*61c4878aSAndroid Build Coastguard Worker00000000, ,"","" 76*61c4878aSAndroid Build Coastguard Worker141c35d5, ,"","The answer: ""%s""" 77*61c4878aSAndroid Build Coastguard Worker29aef586, ,"","1234" 78*61c4878aSAndroid Build Coastguard Worker2b78825f, ,"","[:-)" 79*61c4878aSAndroid Build Coastguard Worker2e668cd6, ,"","Jello, world!" 80*61c4878aSAndroid Build Coastguard Worker31631781, ,"","%d" 81*61c4878aSAndroid Build Coastguard Worker61fd1e26, ,"","%ld" 82*61c4878aSAndroid Build Coastguard Worker68ab92da, ,"","%s there are %x (%.2f) of them%c" 83*61c4878aSAndroid Build Coastguard Worker7b940e2a, ,"","Hello %s! %hd %e" 84*61c4878aSAndroid Build Coastguard Worker7da55d52, ,"",">:-[]" 85*61c4878aSAndroid Build Coastguard Worker7f35a9a5, ,"","TestName" 86*61c4878aSAndroid Build Coastguard Worker851beeb6, ,"","%u %d" 87*61c4878aSAndroid Build Coastguard Worker881436a0, ,"","The answer is: %s" 88*61c4878aSAndroid Build Coastguard Worker88808930, ,"","%u%d%02x%X%hu%hhd%d%ld%lu%lld%llu%c%c%c" 89*61c4878aSAndroid Build Coastguard Worker92723f44, ,"","???" 90*61c4878aSAndroid Build Coastguard Workera09d6698, ,"","won-won-won-wonderful" 91*61c4878aSAndroid Build Coastguard Workeraa9ffa66, ,"","void pw::tokenizer::{anonymous}::TestName()" 92*61c4878aSAndroid Build Coastguard Workerad002c97, ,"","%llx" 93*61c4878aSAndroid Build Coastguard Workerb3653e13, ,"","Jello!" 94*61c4878aSAndroid Build Coastguard Workercc6d3131, ,"","Jello?" 95*61c4878aSAndroid Build Coastguard Workere13b0f94, ,"","%llu" 96*61c4878aSAndroid Build Coastguard Workere65aefef, ,"","Won't fit : %s%d" 97*61c4878aSAndroid Build Coastguard Worker17fa86d3, ,"TEST_DOMAIN","hello" 98*61c4878aSAndroid Build Coastguard Worker18c5017c, ,"TEST_DOMAIN","yes" 99*61c4878aSAndroid Build Coastguard Worker59b2701c, ,"TEST_DOMAIN","The answer was: %s" 100*61c4878aSAndroid Build Coastguard Worker881436a0, ,"TEST_DOMAIN","The answer is: %s" 101*61c4878aSAndroid Build Coastguard Workerd18ada0f, ,"TEST_DOMAIN","something" 102*61c4878aSAndroid Build Coastguard Worker''' 103*61c4878aSAndroid Build Coastguard Worker 104*61c4878aSAndroid Build Coastguard WorkerJSON_SOURCE_STRINGS = '''\ 105*61c4878aSAndroid Build Coastguard Worker[ 106*61c4878aSAndroid Build Coastguard Worker "pigweed/pw_polyfill/standard_library_public/pw_polyfill/standard_library/assert.h", 107*61c4878aSAndroid Build Coastguard Worker "protocol_buffer/gen/pigweed/pw_protobuf/common_protos.proto_library/nanopb/pw_protobuf_protos/status.pb.h", 108*61c4878aSAndroid Build Coastguard Worker "pigweed/pw_rpc/client_server.cc", 109*61c4878aSAndroid Build Coastguard Worker "pigweed/pw_rpc/public/pw_rpc/client_server.h", 110*61c4878aSAndroid Build Coastguard Worker "This is a very long string that will produce two tokens; one for C++ and one for C. This is because this string exceeds the default C hash length." 111*61c4878aSAndroid Build Coastguard Worker] 112*61c4878aSAndroid Build Coastguard Worker''' 113*61c4878aSAndroid Build Coastguard Worker 114*61c4878aSAndroid Build Coastguard WorkerCSV_STRINGS = '''\ 115*61c4878aSAndroid Build Coastguard Worker2cbf627a, ,"","pigweed/pw_rpc/client_server.cc" 116*61c4878aSAndroid Build Coastguard Worker666562a1, ,"","protocol_buffer/gen/pigweed/pw_protobuf/common_protos.proto_library/nanopb/pw_protobuf_protos/status.pb.h" 117*61c4878aSAndroid Build Coastguard Worker6c1e6eb3, ,"","pigweed/pw_rpc/public/pw_rpc/client_server.h" 118*61c4878aSAndroid Build Coastguard Workerb25a9932, ,"","This is a very long string that will produce two tokens; one for C++ and one for C. This is because this string exceeds the default C hash length." 119*61c4878aSAndroid Build Coastguard Workereadf017f, ,"","pigweed/pw_polyfill/standard_library_public/pw_polyfill/standard_library/assert.h" 120*61c4878aSAndroid Build Coastguard Workerf815dc5c, ,"","This is a very long string that will produce two tokens; one for C++ and one for C. This is because this string exceeds the default C hash length." 121*61c4878aSAndroid Build Coastguard Worker''' 122*61c4878aSAndroid Build Coastguard Worker 123*61c4878aSAndroid Build Coastguard WorkerEXPECTED_REPORT = { 124*61c4878aSAndroid Build Coastguard Worker str(TOKENIZED_ENTRIES_ELF): { 125*61c4878aSAndroid Build Coastguard Worker '': { 126*61c4878aSAndroid Build Coastguard Worker 'present_entries': 22, 127*61c4878aSAndroid Build Coastguard Worker 'present_size_bytes': 289, 128*61c4878aSAndroid Build Coastguard Worker 'total_entries': 22, 129*61c4878aSAndroid Build Coastguard Worker 'total_size_bytes': 289, 130*61c4878aSAndroid Build Coastguard Worker 'collisions': {}, 131*61c4878aSAndroid Build Coastguard Worker }, 132*61c4878aSAndroid Build Coastguard Worker 'TEST_DOMAIN': { 133*61c4878aSAndroid Build Coastguard Worker 'present_entries': 5, 134*61c4878aSAndroid Build Coastguard Worker 'present_size_bytes': 57, 135*61c4878aSAndroid Build Coastguard Worker 'total_entries': 5, 136*61c4878aSAndroid Build Coastguard Worker 'total_size_bytes': 57, 137*61c4878aSAndroid Build Coastguard Worker 'collisions': {}, 138*61c4878aSAndroid Build Coastguard Worker }, 139*61c4878aSAndroid Build Coastguard Worker } 140*61c4878aSAndroid Build Coastguard Worker} 141*61c4878aSAndroid Build Coastguard Worker 142*61c4878aSAndroid Build Coastguard Worker 143*61c4878aSAndroid Build Coastguard Workerdef run_cli(*args) -> None: 144*61c4878aSAndroid Build Coastguard Worker original_argv = sys.argv 145*61c4878aSAndroid Build Coastguard Worker sys.argv = ['database.py', *(str(a) for a in args)] 146*61c4878aSAndroid Build Coastguard Worker # pylint: disable=protected-access 147*61c4878aSAndroid Build Coastguard Worker try: 148*61c4878aSAndroid Build Coastguard Worker database._main(*database._parse_args()) 149*61c4878aSAndroid Build Coastguard Worker finally: 150*61c4878aSAndroid Build Coastguard Worker # Remove the log handler added by _main to avoid duplicate logs. 151*61c4878aSAndroid Build Coastguard Worker if database._LOG.handlers: 152*61c4878aSAndroid Build Coastguard Worker database._LOG.handlers.pop() 153*61c4878aSAndroid Build Coastguard Worker # pylint: enable=protected-access 154*61c4878aSAndroid Build Coastguard Worker 155*61c4878aSAndroid Build Coastguard Worker sys.argv = original_argv 156*61c4878aSAndroid Build Coastguard Worker 157*61c4878aSAndroid Build Coastguard Worker 158*61c4878aSAndroid Build Coastguard Workerdef _mock_output() -> io.TextIOWrapper: 159*61c4878aSAndroid Build Coastguard Worker output = io.BytesIO() 160*61c4878aSAndroid Build Coastguard Worker output.name = '<fake stdout>' 161*61c4878aSAndroid Build Coastguard Worker return io.TextIOWrapper(output, write_through=True) 162*61c4878aSAndroid Build Coastguard Worker 163*61c4878aSAndroid Build Coastguard Worker 164*61c4878aSAndroid Build Coastguard Workerdef _remove_readonly( # pylint: disable=unused-argument 165*61c4878aSAndroid Build Coastguard Worker func, path, excinfo 166*61c4878aSAndroid Build Coastguard Worker) -> None: 167*61c4878aSAndroid Build Coastguard Worker """Changes file permission and recalls the calling function.""" 168*61c4878aSAndroid Build Coastguard Worker print('Path attempted to be deleted:', path) 169*61c4878aSAndroid Build Coastguard Worker if not os.access(path, os.W_OK): 170*61c4878aSAndroid Build Coastguard Worker # Change file permissions. 171*61c4878aSAndroid Build Coastguard Worker os.chmod(path, stat.S_IWUSR) 172*61c4878aSAndroid Build Coastguard Worker # Call the calling function again. 173*61c4878aSAndroid Build Coastguard Worker func(path) 174*61c4878aSAndroid Build Coastguard Worker 175*61c4878aSAndroid Build Coastguard Worker 176*61c4878aSAndroid Build Coastguard Workerclass DatabaseCommandLineTest(unittest.TestCase): 177*61c4878aSAndroid Build Coastguard Worker """Tests the database.py command line interface.""" 178*61c4878aSAndroid Build Coastguard Worker 179*61c4878aSAndroid Build Coastguard Worker def setUp(self) -> None: 180*61c4878aSAndroid Build Coastguard Worker self._dir = Path(tempfile.mkdtemp('_pw_tokenizer_test')) 181*61c4878aSAndroid Build Coastguard Worker self._csv = self._dir / 'db.csv' 182*61c4878aSAndroid Build Coastguard Worker self._elf = TOKENIZED_ENTRIES_ELF 183*61c4878aSAndroid Build Coastguard Worker 184*61c4878aSAndroid Build Coastguard Worker def tearDown(self) -> None: 185*61c4878aSAndroid Build Coastguard Worker shutil.rmtree(self._dir) 186*61c4878aSAndroid Build Coastguard Worker 187*61c4878aSAndroid Build Coastguard Worker def test_create_csv(self) -> None: 188*61c4878aSAndroid Build Coastguard Worker run_cli('create', '--database', self._csv, self._elf) 189*61c4878aSAndroid Build Coastguard Worker 190*61c4878aSAndroid Build Coastguard Worker self.assertEqual( 191*61c4878aSAndroid Build Coastguard Worker CSV_ALL_DOMAINS.splitlines(), self._csv.read_text().splitlines() 192*61c4878aSAndroid Build Coastguard Worker ) 193*61c4878aSAndroid Build Coastguard Worker 194*61c4878aSAndroid Build Coastguard Worker def test_create_csv_from_three_column_csv(self) -> None: 195*61c4878aSAndroid Build Coastguard Worker three_col_db = self._dir.joinpath('legacy.csv') 196*61c4878aSAndroid Build Coastguard Worker # Remove the domain column 197*61c4878aSAndroid Build Coastguard Worker three_col_db.write_text(CSV_TEST_DOMAIN.replace('"TEST_DOMAIN",', '')) 198*61c4878aSAndroid Build Coastguard Worker run_cli('create', '--database', self._csv, three_col_db) 199*61c4878aSAndroid Build Coastguard Worker 200*61c4878aSAndroid Build Coastguard Worker tokens_in_default = CSV_TEST_DOMAIN.replace('"TEST_DOMAIN",', '"",') 201*61c4878aSAndroid Build Coastguard Worker self.assertEqual( 202*61c4878aSAndroid Build Coastguard Worker tokens_in_default.splitlines(), self._csv.read_text().splitlines() 203*61c4878aSAndroid Build Coastguard Worker ) 204*61c4878aSAndroid Build Coastguard Worker 205*61c4878aSAndroid Build Coastguard Worker def test_create_csv_test_domain(self) -> None: 206*61c4878aSAndroid Build Coastguard Worker run_cli('create', '--database', self._csv, f'{self._elf}#TEST_DOMAIN') 207*61c4878aSAndroid Build Coastguard Worker 208*61c4878aSAndroid Build Coastguard Worker self.assertEqual( 209*61c4878aSAndroid Build Coastguard Worker CSV_TEST_DOMAIN.splitlines(), 210*61c4878aSAndroid Build Coastguard Worker self._csv.read_text().splitlines(), 211*61c4878aSAndroid Build Coastguard Worker ) 212*61c4878aSAndroid Build Coastguard Worker 213*61c4878aSAndroid Build Coastguard Worker def test_create_csv_all_domains(self) -> None: 214*61c4878aSAndroid Build Coastguard Worker run_cli('create', '--database', self._csv, self._elf) 215*61c4878aSAndroid Build Coastguard Worker 216*61c4878aSAndroid Build Coastguard Worker self.assertEqual( 217*61c4878aSAndroid Build Coastguard Worker CSV_ALL_DOMAINS.splitlines(), self._csv.read_text().splitlines() 218*61c4878aSAndroid Build Coastguard Worker ) 219*61c4878aSAndroid Build Coastguard Worker 220*61c4878aSAndroid Build Coastguard Worker def test_create_csv_all_domains_regex(self) -> None: 221*61c4878aSAndroid Build Coastguard Worker run_cli('create', '--database', self._csv, f'{self._elf}#.*') 222*61c4878aSAndroid Build Coastguard Worker 223*61c4878aSAndroid Build Coastguard Worker self.assertEqual( 224*61c4878aSAndroid Build Coastguard Worker CSV_ALL_DOMAINS.splitlines(), self._csv.read_text().splitlines() 225*61c4878aSAndroid Build Coastguard Worker ) 226*61c4878aSAndroid Build Coastguard Worker 227*61c4878aSAndroid Build Coastguard Worker def test_invalid_domain_pattern(self) -> None: 228*61c4878aSAndroid Build Coastguard Worker with self.assertRaises(SystemExit): 229*61c4878aSAndroid Build Coastguard Worker run_cli('create', '--database', self._csv, f'{self._elf}#.*#') 230*61c4878aSAndroid Build Coastguard Worker 231*61c4878aSAndroid Build Coastguard Worker def test_invalid_glob(self) -> None: 232*61c4878aSAndroid Build Coastguard Worker with self.assertRaises(SystemExit): 233*61c4878aSAndroid Build Coastguard Worker run_cli('create', '--database', self._csv, 'INVALID PATH') 234*61c4878aSAndroid Build Coastguard Worker 235*61c4878aSAndroid Build Coastguard Worker def test_create_force(self) -> None: 236*61c4878aSAndroid Build Coastguard Worker self._csv.write_text(CSV_ALL_DOMAINS) 237*61c4878aSAndroid Build Coastguard Worker 238*61c4878aSAndroid Build Coastguard Worker with self.assertRaises(FileExistsError): 239*61c4878aSAndroid Build Coastguard Worker run_cli('create', '--database', self._csv, self._elf) 240*61c4878aSAndroid Build Coastguard Worker 241*61c4878aSAndroid Build Coastguard Worker run_cli('create', '--force', '--database', self._csv, self._elf) 242*61c4878aSAndroid Build Coastguard Worker 243*61c4878aSAndroid Build Coastguard Worker def test_create_binary(self) -> None: 244*61c4878aSAndroid Build Coastguard Worker binary = self._dir / 'db.bin' 245*61c4878aSAndroid Build Coastguard Worker run_cli( 246*61c4878aSAndroid Build Coastguard Worker 'create', 247*61c4878aSAndroid Build Coastguard Worker '--type', 248*61c4878aSAndroid Build Coastguard Worker 'binary', 249*61c4878aSAndroid Build Coastguard Worker '--database', 250*61c4878aSAndroid Build Coastguard Worker binary, 251*61c4878aSAndroid Build Coastguard Worker f'{self._elf}#', # Only default domain since v1 DB excludes domain. 252*61c4878aSAndroid Build Coastguard Worker ) 253*61c4878aSAndroid Build Coastguard Worker 254*61c4878aSAndroid Build Coastguard Worker # Write the binary database as CSV to verify its contents. 255*61c4878aSAndroid Build Coastguard Worker run_cli('create', '--database', self._csv, binary) 256*61c4878aSAndroid Build Coastguard Worker 257*61c4878aSAndroid Build Coastguard Worker self.assertEqual( 258*61c4878aSAndroid Build Coastguard Worker CSV_DEFAULT_DOMAIN.splitlines(), self._csv.read_text().splitlines() 259*61c4878aSAndroid Build Coastguard Worker ) 260*61c4878aSAndroid Build Coastguard Worker 261*61c4878aSAndroid Build Coastguard Worker def test_add_does_not_recalculate_tokens(self) -> None: 262*61c4878aSAndroid Build Coastguard Worker db_with_custom_token = '01234567, ,"","hello"' 263*61c4878aSAndroid Build Coastguard Worker 264*61c4878aSAndroid Build Coastguard Worker to_add = self._dir / 'add_this.csv' 265*61c4878aSAndroid Build Coastguard Worker to_add.write_text(db_with_custom_token + '\n') 266*61c4878aSAndroid Build Coastguard Worker self._csv.touch() 267*61c4878aSAndroid Build Coastguard Worker 268*61c4878aSAndroid Build Coastguard Worker run_cli('add', '--database', self._csv, to_add) 269*61c4878aSAndroid Build Coastguard Worker self.assertEqual( 270*61c4878aSAndroid Build Coastguard Worker db_with_custom_token.splitlines(), 271*61c4878aSAndroid Build Coastguard Worker self._csv.read_text().splitlines(), 272*61c4878aSAndroid Build Coastguard Worker ) 273*61c4878aSAndroid Build Coastguard Worker 274*61c4878aSAndroid Build Coastguard Worker def test_mark_removed(self) -> None: 275*61c4878aSAndroid Build Coastguard Worker """Tests adding a removal date to tokens in a CSV database.""" 276*61c4878aSAndroid Build Coastguard Worker self._csv.write_text(CSV_ALL_DOMAINS) 277*61c4878aSAndroid Build Coastguard Worker 278*61c4878aSAndroid Build Coastguard Worker run_cli( 279*61c4878aSAndroid Build Coastguard Worker 'mark_removed', 280*61c4878aSAndroid Build Coastguard Worker '--database', 281*61c4878aSAndroid Build Coastguard Worker self._csv, 282*61c4878aSAndroid Build Coastguard Worker '--date', 283*61c4878aSAndroid Build Coastguard Worker '1998-09-04', 284*61c4878aSAndroid Build Coastguard Worker f'{self._elf}#', # Only load the default domain for this test. 285*61c4878aSAndroid Build Coastguard Worker ) 286*61c4878aSAndroid Build Coastguard Worker 287*61c4878aSAndroid Build Coastguard Worker # Add the removal date to the tokens not in the default domain 288*61c4878aSAndroid Build Coastguard Worker new_csv = CSV_ALL_DOMAINS 289*61c4878aSAndroid Build Coastguard Worker new_csv = new_csv.replace( 290*61c4878aSAndroid Build Coastguard Worker '17fa86d3, ,"TEST_DOMAIN","hello"', 291*61c4878aSAndroid Build Coastguard Worker '17fa86d3,1998-09-04,"TEST_DOMAIN","hello"', 292*61c4878aSAndroid Build Coastguard Worker ) 293*61c4878aSAndroid Build Coastguard Worker new_csv = new_csv.replace( 294*61c4878aSAndroid Build Coastguard Worker '18c5017c, ,"TEST_DOMAIN","yes"', 295*61c4878aSAndroid Build Coastguard Worker '18c5017c,1998-09-04,"TEST_DOMAIN","yes"', 296*61c4878aSAndroid Build Coastguard Worker ) 297*61c4878aSAndroid Build Coastguard Worker new_csv = new_csv.replace( 298*61c4878aSAndroid Build Coastguard Worker '59b2701c, ,"TEST_DOMAIN","The answer was: %s"', 299*61c4878aSAndroid Build Coastguard Worker '59b2701c,1998-09-04,"TEST_DOMAIN","The answer was: %s"', 300*61c4878aSAndroid Build Coastguard Worker ) 301*61c4878aSAndroid Build Coastguard Worker new_csv = new_csv.replace( 302*61c4878aSAndroid Build Coastguard Worker 'd18ada0f, ,"TEST_DOMAIN","something"', 303*61c4878aSAndroid Build Coastguard Worker 'd18ada0f,1998-09-04,"TEST_DOMAIN","something"', 304*61c4878aSAndroid Build Coastguard Worker ) 305*61c4878aSAndroid Build Coastguard Worker new_csv = new_csv.replace( 306*61c4878aSAndroid Build Coastguard Worker '881436a0, ,"TEST_DOMAIN","The answer is: %s"', 307*61c4878aSAndroid Build Coastguard Worker '881436a0,1998-09-04,"TEST_DOMAIN","The answer is: %s"', 308*61c4878aSAndroid Build Coastguard Worker ) 309*61c4878aSAndroid Build Coastguard Worker self.assertNotEqual(CSV_ALL_DOMAINS, new_csv) 310*61c4878aSAndroid Build Coastguard Worker 311*61c4878aSAndroid Build Coastguard Worker self.assertEqual( 312*61c4878aSAndroid Build Coastguard Worker new_csv.splitlines(), self._csv.read_text().splitlines() 313*61c4878aSAndroid Build Coastguard Worker ) 314*61c4878aSAndroid Build Coastguard Worker 315*61c4878aSAndroid Build Coastguard Worker def test_purge(self) -> None: 316*61c4878aSAndroid Build Coastguard Worker self._csv.write_text(CSV_DEFAULT_DOMAIN) 317*61c4878aSAndroid Build Coastguard Worker 318*61c4878aSAndroid Build Coastguard Worker first_5_csv = self._dir / 'first_5.csv' 319*61c4878aSAndroid Build Coastguard Worker first_5_csv.write_text( 320*61c4878aSAndroid Build Coastguard Worker ''.join(CSV_DEFAULT_DOMAIN.splitlines(keepends=True)[:5]) 321*61c4878aSAndroid Build Coastguard Worker ) 322*61c4878aSAndroid Build Coastguard Worker 323*61c4878aSAndroid Build Coastguard Worker self._csv.write_text(CSV_DEFAULT_DOMAIN) 324*61c4878aSAndroid Build Coastguard Worker 325*61c4878aSAndroid Build Coastguard Worker # Mark everything except for the first 5 entries as removed. 326*61c4878aSAndroid Build Coastguard Worker run_cli('mark_removed', '--database', self._csv, first_5_csv) 327*61c4878aSAndroid Build Coastguard Worker 328*61c4878aSAndroid Build Coastguard Worker # Delete all entries except those in TEST_DOMAIN. 329*61c4878aSAndroid Build Coastguard Worker run_cli('purge', '--database', self._csv) 330*61c4878aSAndroid Build Coastguard Worker 331*61c4878aSAndroid Build Coastguard Worker self.assertEqual( 332*61c4878aSAndroid Build Coastguard Worker first_5_csv.read_text().splitlines(), 333*61c4878aSAndroid Build Coastguard Worker self._csv.read_text().splitlines(), 334*61c4878aSAndroid Build Coastguard Worker ) 335*61c4878aSAndroid Build Coastguard Worker 336*61c4878aSAndroid Build Coastguard Worker @mock.patch('sys.stdout', new_callable=_mock_output) 337*61c4878aSAndroid Build Coastguard Worker def test_report(self, mock_stdout) -> None: 338*61c4878aSAndroid Build Coastguard Worker run_cli('report', self._elf) 339*61c4878aSAndroid Build Coastguard Worker 340*61c4878aSAndroid Build Coastguard Worker self.assertEqual( 341*61c4878aSAndroid Build Coastguard Worker json.loads(mock_stdout.buffer.getvalue()), EXPECTED_REPORT 342*61c4878aSAndroid Build Coastguard Worker ) 343*61c4878aSAndroid Build Coastguard Worker 344*61c4878aSAndroid Build Coastguard Worker def test_replace(self) -> None: 345*61c4878aSAndroid Build Coastguard Worker sub = 'replace/ment' 346*61c4878aSAndroid Build Coastguard Worker run_cli( 347*61c4878aSAndroid Build Coastguard Worker 'create', 348*61c4878aSAndroid Build Coastguard Worker '--database', 349*61c4878aSAndroid Build Coastguard Worker self._csv, 350*61c4878aSAndroid Build Coastguard Worker f'{self._elf}#', # Only load the default domain for this test. 351*61c4878aSAndroid Build Coastguard Worker '--replace', 352*61c4878aSAndroid Build Coastguard Worker r'(?i)\b[jh]ello\b/' + sub, 353*61c4878aSAndroid Build Coastguard Worker ) 354*61c4878aSAndroid Build Coastguard Worker self.assertEqual( 355*61c4878aSAndroid Build Coastguard Worker CSV_DEFAULT_DOMAIN.replace('Jello', sub).replace('Hello', sub), 356*61c4878aSAndroid Build Coastguard Worker self._csv.read_text(), 357*61c4878aSAndroid Build Coastguard Worker ) 358*61c4878aSAndroid Build Coastguard Worker 359*61c4878aSAndroid Build Coastguard Worker def test_json_strings(self) -> None: 360*61c4878aSAndroid Build Coastguard Worker strings_file = self._dir / "strings.json" 361*61c4878aSAndroid Build Coastguard Worker 362*61c4878aSAndroid Build Coastguard Worker with open(strings_file, 'w') as file: 363*61c4878aSAndroid Build Coastguard Worker file.write(JSON_SOURCE_STRINGS) 364*61c4878aSAndroid Build Coastguard Worker 365*61c4878aSAndroid Build Coastguard Worker run_cli('create', '--force', '--database', self._csv, strings_file) 366*61c4878aSAndroid Build Coastguard Worker self.assertEqual( 367*61c4878aSAndroid Build Coastguard Worker CSV_STRINGS.splitlines(), self._csv.read_text().splitlines() 368*61c4878aSAndroid Build Coastguard Worker ) 369*61c4878aSAndroid Build Coastguard Worker 370*61c4878aSAndroid Build Coastguard Worker 371*61c4878aSAndroid Build Coastguard Workerclass DirectoryDatabaseCommandLineTest(unittest.TestCase): 372*61c4878aSAndroid Build Coastguard Worker """Tests the directory database command line interface.""" 373*61c4878aSAndroid Build Coastguard Worker 374*61c4878aSAndroid Build Coastguard Worker def setUp(self) -> None: 375*61c4878aSAndroid Build Coastguard Worker self._dir = Path(tempfile.mkdtemp('_pw_tokenizer_test')) 376*61c4878aSAndroid Build Coastguard Worker self._db_dir = self._dir / '_dir_database_test' 377*61c4878aSAndroid Build Coastguard Worker self._db_dir.mkdir(exist_ok=True) 378*61c4878aSAndroid Build Coastguard Worker self._db_csv = self._db_dir / '8123913.pw_tokenizer.csv' 379*61c4878aSAndroid Build Coastguard Worker self._elf = TOKENIZED_ENTRIES_ELF 380*61c4878aSAndroid Build Coastguard Worker 381*61c4878aSAndroid Build Coastguard Worker def _git(self, *command: str) -> None: 382*61c4878aSAndroid Build Coastguard Worker """Runs git in self._dir with forced user name and email values. 383*61c4878aSAndroid Build Coastguard Worker 384*61c4878aSAndroid Build Coastguard Worker Prevents accidentally running git in the wrong directory and avoids 385*61c4878aSAndroid Build Coastguard Worker errors if the name and email are not configured. 386*61c4878aSAndroid Build Coastguard Worker """ 387*61c4878aSAndroid Build Coastguard Worker subprocess.run( 388*61c4878aSAndroid Build Coastguard Worker [ 389*61c4878aSAndroid Build Coastguard Worker 'git', 390*61c4878aSAndroid Build Coastguard Worker '-c', 391*61c4878aSAndroid Build Coastguard Worker 'user.name=pw_tokenizer tests', 392*61c4878aSAndroid Build Coastguard Worker '-c', 393*61c4878aSAndroid Build Coastguard Worker '[email protected]', 394*61c4878aSAndroid Build Coastguard Worker *command, 395*61c4878aSAndroid Build Coastguard Worker ], 396*61c4878aSAndroid Build Coastguard Worker cwd=self._dir, 397*61c4878aSAndroid Build Coastguard Worker check=True, 398*61c4878aSAndroid Build Coastguard Worker ) 399*61c4878aSAndroid Build Coastguard Worker 400*61c4878aSAndroid Build Coastguard Worker def tearDown(self) -> None: 401*61c4878aSAndroid Build Coastguard Worker shutil.rmtree(self._dir, onerror=_remove_readonly) 402*61c4878aSAndroid Build Coastguard Worker 403*61c4878aSAndroid Build Coastguard Worker def test_add_csv_to_dir(self) -> None: 404*61c4878aSAndroid Build Coastguard Worker """Tests a CSV can be created within the database.""" 405*61c4878aSAndroid Build Coastguard Worker run_cli('add', '--database', self._db_dir, f'{self._elf}#TEST_DOMAIN') 406*61c4878aSAndroid Build Coastguard Worker directory = list(self._db_dir.iterdir()) 407*61c4878aSAndroid Build Coastguard Worker 408*61c4878aSAndroid Build Coastguard Worker self.assertEqual(1, len(directory)) 409*61c4878aSAndroid Build Coastguard Worker 410*61c4878aSAndroid Build Coastguard Worker self._db_csv = directory.pop() 411*61c4878aSAndroid Build Coastguard Worker 412*61c4878aSAndroid Build Coastguard Worker self.assertEqual( 413*61c4878aSAndroid Build Coastguard Worker CSV_TEST_DOMAIN.splitlines(), 414*61c4878aSAndroid Build Coastguard Worker self._db_csv.read_text().splitlines(), 415*61c4878aSAndroid Build Coastguard Worker ) 416*61c4878aSAndroid Build Coastguard Worker 417*61c4878aSAndroid Build Coastguard Worker def test_add_all_domains_to_dir(self) -> None: 418*61c4878aSAndroid Build Coastguard Worker """Tests a CSV with all domains can be added to the database.""" 419*61c4878aSAndroid Build Coastguard Worker run_cli('add', '--database', self._db_dir, f'{self._elf}#.*') 420*61c4878aSAndroid Build Coastguard Worker directory = list(self._db_dir.iterdir()) 421*61c4878aSAndroid Build Coastguard Worker 422*61c4878aSAndroid Build Coastguard Worker self.assertEqual(1, len(directory)) 423*61c4878aSAndroid Build Coastguard Worker 424*61c4878aSAndroid Build Coastguard Worker self._db_csv = directory.pop() 425*61c4878aSAndroid Build Coastguard Worker 426*61c4878aSAndroid Build Coastguard Worker self.assertEqual( 427*61c4878aSAndroid Build Coastguard Worker CSV_ALL_DOMAINS.splitlines(), self._db_csv.read_text().splitlines() 428*61c4878aSAndroid Build Coastguard Worker ) 429*61c4878aSAndroid Build Coastguard Worker 430*61c4878aSAndroid Build Coastguard Worker def test_not_adding_existing_tokens(self) -> None: 431*61c4878aSAndroid Build Coastguard Worker """Tests duplicate tokens are not added to the database.""" 432*61c4878aSAndroid Build Coastguard Worker run_cli('add', '--database', self._db_dir, self._elf) 433*61c4878aSAndroid Build Coastguard Worker run_cli('add', '--database', self._db_dir, self._elf) 434*61c4878aSAndroid Build Coastguard Worker directory = list(self._db_dir.iterdir()) 435*61c4878aSAndroid Build Coastguard Worker 436*61c4878aSAndroid Build Coastguard Worker self.assertEqual(1, len(directory)) 437*61c4878aSAndroid Build Coastguard Worker 438*61c4878aSAndroid Build Coastguard Worker self._db_csv = directory.pop() 439*61c4878aSAndroid Build Coastguard Worker 440*61c4878aSAndroid Build Coastguard Worker self.assertEqual( 441*61c4878aSAndroid Build Coastguard Worker CSV_ALL_DOMAINS.splitlines(), 442*61c4878aSAndroid Build Coastguard Worker self._db_csv.read_text().splitlines(), 443*61c4878aSAndroid Build Coastguard Worker ) 444*61c4878aSAndroid Build Coastguard Worker 445*61c4878aSAndroid Build Coastguard Worker def test_adding_tokens_without_git_repo(self): 446*61c4878aSAndroid Build Coastguard Worker """Tests creating new files with new entries when no repo exists.""" 447*61c4878aSAndroid Build Coastguard Worker # Add a subset of entries to a new CSV in the directory database. 448*61c4878aSAndroid Build Coastguard Worker entry_subset = self._dir / 'entry_subset.csv' 449*61c4878aSAndroid Build Coastguard Worker entry_subset.write_text(CSV_TEST_DOMAIN) 450*61c4878aSAndroid Build Coastguard Worker 451*61c4878aSAndroid Build Coastguard Worker run_cli('add', '--database', self._db_dir, entry_subset) 452*61c4878aSAndroid Build Coastguard Worker directory = list(self._db_dir.iterdir()) 453*61c4878aSAndroid Build Coastguard Worker 454*61c4878aSAndroid Build Coastguard Worker self.assertEqual(1, len(directory)) 455*61c4878aSAndroid Build Coastguard Worker 456*61c4878aSAndroid Build Coastguard Worker first_csv_in_db = directory.pop() 457*61c4878aSAndroid Build Coastguard Worker 458*61c4878aSAndroid Build Coastguard Worker self.assertEqual( 459*61c4878aSAndroid Build Coastguard Worker CSV_TEST_DOMAIN.splitlines(), 460*61c4878aSAndroid Build Coastguard Worker first_csv_in_db.read_text().splitlines(), 461*61c4878aSAndroid Build Coastguard Worker ) 462*61c4878aSAndroid Build Coastguard Worker # Add a superset of entries to a new CSV in the directory database. 463*61c4878aSAndroid Build Coastguard Worker entry_superset = self._dir / 'entry_superset.csv' 464*61c4878aSAndroid Build Coastguard Worker entry_superset.write_text(CSV_ALL_DOMAINS) 465*61c4878aSAndroid Build Coastguard Worker 466*61c4878aSAndroid Build Coastguard Worker run_cli('add', '--database', self._db_dir, entry_superset) 467*61c4878aSAndroid Build Coastguard Worker directory = list(self._db_dir.iterdir()) 468*61c4878aSAndroid Build Coastguard Worker # Assert two different CSVs were created to store new tokens. 469*61c4878aSAndroid Build Coastguard Worker self.assertEqual(2, len(directory)) 470*61c4878aSAndroid Build Coastguard Worker # Retrieve the other CSV in the directory. 471*61c4878aSAndroid Build Coastguard Worker second_csv_in_db = ( 472*61c4878aSAndroid Build Coastguard Worker directory[0] if directory[0] != first_csv_in_db else directory[1] 473*61c4878aSAndroid Build Coastguard Worker ) 474*61c4878aSAndroid Build Coastguard Worker 475*61c4878aSAndroid Build Coastguard Worker self.assertNotEqual(first_csv_in_db, second_csv_in_db) 476*61c4878aSAndroid Build Coastguard Worker self.assertEqual( 477*61c4878aSAndroid Build Coastguard Worker CSV_TEST_DOMAIN.splitlines(), 478*61c4878aSAndroid Build Coastguard Worker first_csv_in_db.read_text().splitlines(), 479*61c4878aSAndroid Build Coastguard Worker ) 480*61c4878aSAndroid Build Coastguard Worker 481*61c4878aSAndroid Build Coastguard Worker # Retrieve entries exclusively in the superset, not the subset. 482*61c4878aSAndroid Build Coastguard Worker entries_exclusively_in_superset = set( 483*61c4878aSAndroid Build Coastguard Worker CSV_ALL_DOMAINS.splitlines() 484*61c4878aSAndroid Build Coastguard Worker ) - set(CSV_TEST_DOMAIN.splitlines()) 485*61c4878aSAndroid Build Coastguard Worker # Ensure only new tokens not in the subset were added to the second CSV 486*61c4878aSAndroid Build Coastguard Worker # added to the directory database. 487*61c4878aSAndroid Build Coastguard Worker self.assertEqual( 488*61c4878aSAndroid Build Coastguard Worker entries_exclusively_in_superset, 489*61c4878aSAndroid Build Coastguard Worker set(second_csv_in_db.read_text().splitlines()), 490*61c4878aSAndroid Build Coastguard Worker ) 491*61c4878aSAndroid Build Coastguard Worker 492*61c4878aSAndroid Build Coastguard Worker def test_untracked_files_in_dir(self): 493*61c4878aSAndroid Build Coastguard Worker """Tests untracked CSVs are reused by the database.""" 494*61c4878aSAndroid Build Coastguard Worker self._git('init') 495*61c4878aSAndroid Build Coastguard Worker # Add CSV_TEST_DOMAIN to a new CSV in the directory database. 496*61c4878aSAndroid Build Coastguard Worker run_cli( 497*61c4878aSAndroid Build Coastguard Worker 'add', 498*61c4878aSAndroid Build Coastguard Worker '--database', 499*61c4878aSAndroid Build Coastguard Worker self._db_dir, 500*61c4878aSAndroid Build Coastguard Worker '--discard-temporary', 501*61c4878aSAndroid Build Coastguard Worker 'HEAD', 502*61c4878aSAndroid Build Coastguard Worker f'{self._elf}#TEST_DOMAIN', 503*61c4878aSAndroid Build Coastguard Worker ) 504*61c4878aSAndroid Build Coastguard Worker directory = list(self._db_dir.iterdir()) 505*61c4878aSAndroid Build Coastguard Worker 506*61c4878aSAndroid Build Coastguard Worker self.assertEqual(1, len(directory)) 507*61c4878aSAndroid Build Coastguard Worker 508*61c4878aSAndroid Build Coastguard Worker first_path_in_db = directory.pop() 509*61c4878aSAndroid Build Coastguard Worker 510*61c4878aSAndroid Build Coastguard Worker self.assertEqual( 511*61c4878aSAndroid Build Coastguard Worker CSV_TEST_DOMAIN.splitlines(), 512*61c4878aSAndroid Build Coastguard Worker first_path_in_db.read_text().splitlines(), 513*61c4878aSAndroid Build Coastguard Worker ) 514*61c4878aSAndroid Build Coastguard Worker # Retrieve the untracked CSV in the Git repository and discard 515*61c4878aSAndroid Build Coastguard Worker # tokens that do not exist in CSV_DEFAULT_DOMAIN. 516*61c4878aSAndroid Build Coastguard Worker run_cli( 517*61c4878aSAndroid Build Coastguard Worker 'add', 518*61c4878aSAndroid Build Coastguard Worker '--database', 519*61c4878aSAndroid Build Coastguard Worker self._db_dir, 520*61c4878aSAndroid Build Coastguard Worker '--discard-temporary', 521*61c4878aSAndroid Build Coastguard Worker 'HEAD', 522*61c4878aSAndroid Build Coastguard Worker self._elf, 523*61c4878aSAndroid Build Coastguard Worker ) 524*61c4878aSAndroid Build Coastguard Worker directory = list(self._db_dir.iterdir()) 525*61c4878aSAndroid Build Coastguard Worker 526*61c4878aSAndroid Build Coastguard Worker self.assertEqual(1, len(directory)) 527*61c4878aSAndroid Build Coastguard Worker 528*61c4878aSAndroid Build Coastguard Worker reused_path_in_db = directory.pop() 529*61c4878aSAndroid Build Coastguard Worker # Ensure the first path created is the same being reused. Also, 530*61c4878aSAndroid Build Coastguard Worker # the CSV content is the same as CSV_DEFAULT_DOMAIN. 531*61c4878aSAndroid Build Coastguard Worker self.assertEqual(first_path_in_db, reused_path_in_db) 532*61c4878aSAndroid Build Coastguard Worker self.assertEqual( 533*61c4878aSAndroid Build Coastguard Worker CSV_ALL_DOMAINS.splitlines(), 534*61c4878aSAndroid Build Coastguard Worker reused_path_in_db.read_text().splitlines(), 535*61c4878aSAndroid Build Coastguard Worker ) 536*61c4878aSAndroid Build Coastguard Worker 537*61c4878aSAndroid Build Coastguard Worker def test_adding_multiple_elf_files(self) -> None: 538*61c4878aSAndroid Build Coastguard Worker """Tests adding multiple elf files to a file in the database.""" 539*61c4878aSAndroid Build Coastguard Worker # Add CSV_TEST_DOMAIN to a new CSV in the directory database. 540*61c4878aSAndroid Build Coastguard Worker run_cli( 541*61c4878aSAndroid Build Coastguard Worker 'add', 542*61c4878aSAndroid Build Coastguard Worker '--database', 543*61c4878aSAndroid Build Coastguard Worker self._db_dir, 544*61c4878aSAndroid Build Coastguard Worker f'{self._elf}#TEST_DOMAIN', 545*61c4878aSAndroid Build Coastguard Worker self._elf, 546*61c4878aSAndroid Build Coastguard Worker ) 547*61c4878aSAndroid Build Coastguard Worker directory = list(self._db_dir.iterdir()) 548*61c4878aSAndroid Build Coastguard Worker 549*61c4878aSAndroid Build Coastguard Worker self.assertEqual(1, len(directory)) 550*61c4878aSAndroid Build Coastguard Worker # Combines CSV_DEFAULT_DOMAIN and TEST_DOMAIN into a unique set 551*61c4878aSAndroid Build Coastguard Worker # of token entries. 552*61c4878aSAndroid Build Coastguard Worker entries_from_default_and_test_domain = set( 553*61c4878aSAndroid Build Coastguard Worker CSV_DEFAULT_DOMAIN.splitlines() 554*61c4878aSAndroid Build Coastguard Worker ).union(set(CSV_TEST_DOMAIN.splitlines())) 555*61c4878aSAndroid Build Coastguard Worker # Multiple ELF files were added at once to a single CSV. 556*61c4878aSAndroid Build Coastguard Worker self.assertEqual( 557*61c4878aSAndroid Build Coastguard Worker entries_from_default_and_test_domain, 558*61c4878aSAndroid Build Coastguard Worker set(directory.pop().read_text().splitlines()), 559*61c4878aSAndroid Build Coastguard Worker ) 560*61c4878aSAndroid Build Coastguard Worker 561*61c4878aSAndroid Build Coastguard Worker def test_discarding_old_entries(self) -> None: 562*61c4878aSAndroid Build Coastguard Worker """Tests discarding old entries for new entries when re-adding.""" 563*61c4878aSAndroid Build Coastguard Worker self._git('init') 564*61c4878aSAndroid Build Coastguard Worker # Add CSV_ALL_DOMAINS to a new CSV in the directory database. 565*61c4878aSAndroid Build Coastguard Worker run_cli( 566*61c4878aSAndroid Build Coastguard Worker 'add', 567*61c4878aSAndroid Build Coastguard Worker '--database', 568*61c4878aSAndroid Build Coastguard Worker self._db_dir, 569*61c4878aSAndroid Build Coastguard Worker '--discard-temporary', 570*61c4878aSAndroid Build Coastguard Worker 'HEAD', 571*61c4878aSAndroid Build Coastguard Worker f'{self._elf}#.*', 572*61c4878aSAndroid Build Coastguard Worker ) 573*61c4878aSAndroid Build Coastguard Worker directory = list(self._db_dir.iterdir()) 574*61c4878aSAndroid Build Coastguard Worker 575*61c4878aSAndroid Build Coastguard Worker self.assertEqual(1, len(directory)) 576*61c4878aSAndroid Build Coastguard Worker 577*61c4878aSAndroid Build Coastguard Worker untracked_path_in_db = directory.pop() 578*61c4878aSAndroid Build Coastguard Worker 579*61c4878aSAndroid Build Coastguard Worker self.assertEqual( 580*61c4878aSAndroid Build Coastguard Worker CSV_ALL_DOMAINS.splitlines(), 581*61c4878aSAndroid Build Coastguard Worker untracked_path_in_db.read_text().splitlines(), 582*61c4878aSAndroid Build Coastguard Worker ) 583*61c4878aSAndroid Build Coastguard Worker # Add CSV_DEFAULT_DOMAIN and CSV_TEST_DOMAIN to a CSV in the 584*61c4878aSAndroid Build Coastguard Worker # directory database, while replacing entries in CSV_ALL_DOMAINS 585*61c4878aSAndroid Build Coastguard Worker # that no longer exist. 586*61c4878aSAndroid Build Coastguard Worker run_cli( 587*61c4878aSAndroid Build Coastguard Worker 'add', 588*61c4878aSAndroid Build Coastguard Worker '--database', 589*61c4878aSAndroid Build Coastguard Worker self._db_dir, 590*61c4878aSAndroid Build Coastguard Worker '--discard-temporary', 591*61c4878aSAndroid Build Coastguard Worker 'HEAD', 592*61c4878aSAndroid Build Coastguard Worker f'{self._elf}#TEST_DOMAIN', 593*61c4878aSAndroid Build Coastguard Worker self._elf, 594*61c4878aSAndroid Build Coastguard Worker ) 595*61c4878aSAndroid Build Coastguard Worker directory = list(self._db_dir.iterdir()) 596*61c4878aSAndroid Build Coastguard Worker 597*61c4878aSAndroid Build Coastguard Worker self.assertEqual(1, len(directory)) 598*61c4878aSAndroid Build Coastguard Worker 599*61c4878aSAndroid Build Coastguard Worker reused_path_in_db = directory.pop() 600*61c4878aSAndroid Build Coastguard Worker # Combines CSV_DEFAULT_DOMAIN and TEST_DOMAIN. 601*61c4878aSAndroid Build Coastguard Worker entries_from_default_and_test_domain = set( 602*61c4878aSAndroid Build Coastguard Worker CSV_DEFAULT_DOMAIN.splitlines() 603*61c4878aSAndroid Build Coastguard Worker ).union(set(CSV_TEST_DOMAIN.splitlines())) 604*61c4878aSAndroid Build Coastguard Worker 605*61c4878aSAndroid Build Coastguard Worker self.assertEqual(untracked_path_in_db, reused_path_in_db) 606*61c4878aSAndroid Build Coastguard Worker self.assertEqual( 607*61c4878aSAndroid Build Coastguard Worker entries_from_default_and_test_domain, 608*61c4878aSAndroid Build Coastguard Worker set(reused_path_in_db.read_text().splitlines()), 609*61c4878aSAndroid Build Coastguard Worker ) 610*61c4878aSAndroid Build Coastguard Worker 611*61c4878aSAndroid Build Coastguard Worker def test_retrieving_csv_from_commit(self) -> None: 612*61c4878aSAndroid Build Coastguard Worker """Tests retrieving a CSV from a commit and removing temp tokens.""" 613*61c4878aSAndroid Build Coastguard Worker self._git('init') 614*61c4878aSAndroid Build Coastguard Worker self._git('commit', '--allow-empty', '-m', 'First Commit') 615*61c4878aSAndroid Build Coastguard Worker # Add CSV_ALL_DOMAINS to a new CSV in the directory database. 616*61c4878aSAndroid Build Coastguard Worker run_cli('add', '--database', self._db_dir, f'{self._elf}#.*') 617*61c4878aSAndroid Build Coastguard Worker directory = list(self._db_dir.iterdir()) 618*61c4878aSAndroid Build Coastguard Worker 619*61c4878aSAndroid Build Coastguard Worker self.assertEqual(1, len(directory)) 620*61c4878aSAndroid Build Coastguard Worker 621*61c4878aSAndroid Build Coastguard Worker tracked_path_in_db = directory.pop() 622*61c4878aSAndroid Build Coastguard Worker 623*61c4878aSAndroid Build Coastguard Worker self.assertEqual( 624*61c4878aSAndroid Build Coastguard Worker CSV_ALL_DOMAINS.splitlines(), 625*61c4878aSAndroid Build Coastguard Worker tracked_path_in_db.read_text().splitlines(), 626*61c4878aSAndroid Build Coastguard Worker ) 627*61c4878aSAndroid Build Coastguard Worker # Commit the CSV to avoid retrieving the CSV with the checks 628*61c4878aSAndroid Build Coastguard Worker # for untracked changes. 629*61c4878aSAndroid Build Coastguard Worker self._git('add', '--all') 630*61c4878aSAndroid Build Coastguard Worker self._git('commit', '-m', 'Adding a CSV to a new commit.') 631*61c4878aSAndroid Build Coastguard Worker # Retrieve the CSV in HEAD~ and discard tokens that exist in 632*61c4878aSAndroid Build Coastguard Worker # CSV_ALL_DOMAINS and not exist in CSV_TEST_DOMAIN. 633*61c4878aSAndroid Build Coastguard Worker run_cli( 634*61c4878aSAndroid Build Coastguard Worker 'add', 635*61c4878aSAndroid Build Coastguard Worker '--database', 636*61c4878aSAndroid Build Coastguard Worker self._db_dir, 637*61c4878aSAndroid Build Coastguard Worker '--discard-temporary', 638*61c4878aSAndroid Build Coastguard Worker 'HEAD~2', 639*61c4878aSAndroid Build Coastguard Worker f'{self._elf}#TEST_DOMAIN', 640*61c4878aSAndroid Build Coastguard Worker ) 641*61c4878aSAndroid Build Coastguard Worker directory = list(self._db_dir.iterdir()) 642*61c4878aSAndroid Build Coastguard Worker 643*61c4878aSAndroid Build Coastguard Worker self.assertEqual(1, len(directory)) 644*61c4878aSAndroid Build Coastguard Worker 645*61c4878aSAndroid Build Coastguard Worker reused_path_in_db = directory.pop() 646*61c4878aSAndroid Build Coastguard Worker 647*61c4878aSAndroid Build Coastguard Worker self.assertEqual( 648*61c4878aSAndroid Build Coastguard Worker CSV_TEST_DOMAIN.splitlines(), 649*61c4878aSAndroid Build Coastguard Worker reused_path_in_db.read_text().splitlines(), 650*61c4878aSAndroid Build Coastguard Worker ) 651*61c4878aSAndroid Build Coastguard Worker 652*61c4878aSAndroid Build Coastguard Worker 653*61c4878aSAndroid Build Coastguard Workerif __name__ == '__main__': 654*61c4878aSAndroid Build Coastguard Worker unittest.main() 655