1 /*
2  * Copyright (C) 2020 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 
17 #include <filesystem>
18 #include <string>
19 
20 #include <errno.h>
21 #include <sys/stat.h>
22 
23 #include <android-base/file.h>
24 #include <android-base/logging.h>
25 #include <android-base/stringprintf.h>
26 #include <gmock/gmock.h>
27 #include <gtest/gtest.h>
28 
29 #include "apex_file.h"
30 #include "apex_file_repository.h"
31 #include "apexd_test_utils.h"
32 #include "apexd_verity.h"
33 
34 namespace android {
35 namespace apex {
36 
37 using namespace std::literals;
38 
39 namespace fs = std::filesystem;
40 
41 using android::apex::testing::ApexFileEq;
42 using android::apex::testing::IsOk;
43 using android::base::GetExecutableDirectory;
44 using android::base::StringPrintf;
45 using ::testing::ByRef;
46 using ::testing::UnorderedElementsAre;
47 
GetTestDataDir()48 static std::string GetTestDataDir() { return GetExecutableDirectory(); }
GetTestFile(const std::string & name)49 static std::string GetTestFile(const std::string& name) {
50   return GetTestDataDir() + "/" + name;
51 }
52 
53 namespace {
54 // Copies the compressed apex to |built_in_dir| and decompresses it to
55 // |decompression_dir
PrepareCompressedApex(const std::string & name,const std::string & built_in_dir,const std::string & decompression_dir)56 void PrepareCompressedApex(const std::string& name,
57                            const std::string& built_in_dir,
58                            const std::string& decompression_dir) {
59   fs::copy(GetTestFile(name), built_in_dir);
60   auto compressed_apex =
61       ApexFile::Open(StringPrintf("%s/%s", built_in_dir.c_str(), name.c_str()));
62 
63   const auto& pkg_name = compressed_apex->GetManifest().name();
64   const int version = compressed_apex->GetManifest().version();
65 
66   auto decompression_path =
67       StringPrintf("%s/%s@%d%s", decompression_dir.c_str(), pkg_name.c_str(),
68                    version, kDecompressedApexPackageSuffix);
69   compressed_apex->Decompress(decompression_path);
70 }
71 }  // namespace
72 
TEST(ApexFileRepositoryTest,InitializeSuccess)73 TEST(ApexFileRepositoryTest, InitializeSuccess) {
74   // Prepare test data.
75   TemporaryDir built_in_dir, data_dir, decompression_dir;
76   fs::copy(GetTestFile("apex.apexd_test.apex"), built_in_dir.path);
77   fs::copy(GetTestFile("apex.apexd_test_different_app.apex"),
78            built_in_dir.path);
79 
80   fs::copy(GetTestFile("apex.apexd_test.apex"), data_dir.path);
81   fs::copy(GetTestFile("apex.apexd_test_different_app.apex"), data_dir.path);
82 
83   ApexFileRepository instance;
84   ASSERT_TRUE(IsOk(instance.AddPreInstalledApex({built_in_dir.path})));
85   ASSERT_TRUE(IsOk(instance.AddDataApex(data_dir.path)));
86 
87   // Now test that apexes were scanned correctly;
88   auto test_fn = [&](const std::string& apex_name) {
89     auto apex = ApexFile::Open(GetTestFile(apex_name));
90     ASSERT_TRUE(IsOk(apex));
91 
92     {
93       auto ret = instance.GetPublicKey(apex->GetManifest().name());
94       ASSERT_TRUE(IsOk(ret));
95       ASSERT_EQ(apex->GetBundledPublicKey(), *ret);
96     }
97 
98     {
99       auto ret = instance.GetPreinstalledPath(apex->GetManifest().name());
100       ASSERT_TRUE(IsOk(ret));
101       ASSERT_EQ(StringPrintf("%s/%s", built_in_dir.path, apex_name.c_str()),
102                 *ret);
103     }
104 
105     {
106       auto ret = instance.GetDataPath(apex->GetManifest().name());
107       ASSERT_TRUE(IsOk(ret));
108       ASSERT_EQ(StringPrintf("%s/%s", data_dir.path, apex_name.c_str()), *ret);
109     }
110 
111     ASSERT_TRUE(instance.HasPreInstalledVersion(apex->GetManifest().name()));
112     ASSERT_TRUE(instance.HasDataVersion(apex->GetManifest().name()));
113   };
114 
115   test_fn("apex.apexd_test.apex");
116   test_fn("apex.apexd_test_different_app.apex");
117 
118   // Check that second call will succeed as well.
119   ASSERT_TRUE(IsOk(instance.AddPreInstalledApex({built_in_dir.path})));
120   ASSERT_TRUE(IsOk(instance.AddDataApex(data_dir.path)));
121 
122   test_fn("apex.apexd_test.apex");
123   test_fn("apex.apexd_test_different_app.apex");
124 }
125 
TEST(ApexFileRepositoryTest,InitializeFailureCorruptApex)126 TEST(ApexFileRepositoryTest, InitializeFailureCorruptApex) {
127   // Prepare test data.
128   TemporaryDir td;
129   fs::copy(GetTestFile("apex.apexd_test.apex"), td.path);
130   fs::copy(GetTestFile("apex.apexd_test_corrupt_superblock_apex.apex"),
131            td.path);
132 
133   ApexFileRepository instance;
134   ASSERT_FALSE(IsOk(instance.AddPreInstalledApex({td.path})));
135 }
136 
TEST(ApexFileRepositoryTest,InitializeCompressedApexWithoutApex)137 TEST(ApexFileRepositoryTest, InitializeCompressedApexWithoutApex) {
138   // Prepare test data.
139   TemporaryDir td;
140   fs::copy(GetTestFile("com.android.apex.compressed.v1_without_apex.capex"),
141            td.path);
142 
143   ApexFileRepository instance;
144   // Compressed APEX without APEX cannot be opened
145   ASSERT_FALSE(IsOk(instance.AddPreInstalledApex({td.path})));
146 }
147 
TEST(ApexFileRepositoryTest,InitializeSameNameDifferentPathAborts)148 TEST(ApexFileRepositoryTest, InitializeSameNameDifferentPathAborts) {
149   // Prepare test data.
150   TemporaryDir td;
151   fs::copy(GetTestFile("apex.apexd_test.apex"), td.path);
152   fs::copy(GetTestFile("apex.apexd_test.apex"),
153            StringPrintf("%s/other.apex", td.path));
154 
155   ASSERT_DEATH(
156       {
157         ApexFileRepository instance;
158         instance.AddPreInstalledApex({td.path});
159       },
160       "");
161 }
162 
TEST(ApexFileRepositoryTest,InitializeSameNameDifferentPathAbortsCompressedApex)163 TEST(ApexFileRepositoryTest,
164      InitializeSameNameDifferentPathAbortsCompressedApex) {
165   // Prepare test data.
166   TemporaryDir td;
167   fs::copy(GetTestFile("com.android.apex.compressed.v1.capex"), td.path);
168   fs::copy(GetTestFile("com.android.apex.compressed.v1.capex"),
169            StringPrintf("%s/other.capex", td.path));
170 
171   ASSERT_DEATH(
172       {
173         ApexFileRepository instance;
174         instance.AddPreInstalledApex({td.path});
175       },
176       "");
177 }
178 
TEST(ApexFileRepositoryTest,InitializePublicKeyUnexpectdlyChangedAborts)179 TEST(ApexFileRepositoryTest, InitializePublicKeyUnexpectdlyChangedAborts) {
180   // Prepare test data.
181   TemporaryDir td;
182   fs::copy(GetTestFile("apex.apexd_test.apex"), td.path);
183 
184   ApexFileRepository instance;
185   ASSERT_TRUE(IsOk(instance.AddPreInstalledApex({td.path})));
186 
187   // Check that apex was loaded.
188   auto path = instance.GetPreinstalledPath("com.android.apex.test_package");
189   ASSERT_TRUE(IsOk(path));
190   ASSERT_EQ(StringPrintf("%s/apex.apexd_test.apex", td.path), *path);
191 
192   auto public_key = instance.GetPublicKey("com.android.apex.test_package");
193   ASSERT_TRUE(IsOk(public_key));
194 
195   // Substitute it with another apex with the same name, but different public
196   // key.
197   fs::copy(GetTestFile("apex.apexd_test_different_key.apex"), *path,
198            fs::copy_options::overwrite_existing);
199 
200   {
201     auto apex = ApexFile::Open(*path);
202     ASSERT_TRUE(IsOk(apex));
203     // Check module name hasn't changed.
204     ASSERT_EQ("com.android.apex.test_package", apex->GetManifest().name());
205     // Check public key has changed.
206     ASSERT_NE(*public_key, apex->GetBundledPublicKey());
207   }
208 
209   ASSERT_DEATH({ instance.AddPreInstalledApex({td.path}); }, "");
210 }
211 
TEST(ApexFileRepositoryTest,InitializePublicKeyUnexpectdlyChangedAbortsCompressedApex)212 TEST(ApexFileRepositoryTest,
213      InitializePublicKeyUnexpectdlyChangedAbortsCompressedApex) {
214   // Prepare test data.
215   TemporaryDir td;
216   fs::copy(GetTestFile("com.android.apex.compressed.v1.capex"), td.path);
217 
218   ApexFileRepository instance;
219   ASSERT_TRUE(IsOk(instance.AddPreInstalledApex({td.path})));
220 
221   // Check that apex was loaded.
222   auto path = instance.GetPreinstalledPath("com.android.apex.compressed");
223   ASSERT_TRUE(IsOk(path));
224   ASSERT_EQ(StringPrintf("%s/com.android.apex.compressed.v1.capex", td.path),
225             *path);
226 
227   auto public_key = instance.GetPublicKey("com.android.apex.compressed");
228   ASSERT_TRUE(IsOk(public_key));
229 
230   // Substitute it with another apex with the same name, but different public
231   // key.
232   fs::copy(GetTestFile("com.android.apex.compressed_different_key.capex"),
233            *path, fs::copy_options::overwrite_existing);
234 
235   {
236     auto apex = ApexFile::Open(*path);
237     ASSERT_TRUE(IsOk(apex));
238     // Check module name hasn't changed.
239     ASSERT_EQ("com.android.apex.compressed", apex->GetManifest().name());
240     // Check public key has changed.
241     ASSERT_NE(*public_key, apex->GetBundledPublicKey());
242   }
243 
244   ASSERT_DEATH({ instance.AddPreInstalledApex({td.path}); }, "");
245 }
246 
TEST(ApexFileRepositoryTest,IsPreInstalledApex)247 TEST(ApexFileRepositoryTest, IsPreInstalledApex) {
248   // Prepare test data.
249   TemporaryDir td;
250   fs::copy(GetTestFile("apex.apexd_test.apex"), td.path);
251   fs::copy(GetTestFile("com.android.apex.compressed.v1.capex"), td.path);
252 
253   ApexFileRepository instance;
254   ASSERT_TRUE(IsOk(instance.AddPreInstalledApex({td.path})));
255 
256   auto compressed_apex = ApexFile::Open(
257       StringPrintf("%s/com.android.apex.compressed.v1.capex", td.path));
258   ASSERT_TRUE(IsOk(compressed_apex));
259   ASSERT_TRUE(instance.IsPreInstalledApex(*compressed_apex));
260 
261   auto apex1 = ApexFile::Open(StringPrintf("%s/apex.apexd_test.apex", td.path));
262   ASSERT_TRUE(IsOk(apex1));
263   ASSERT_TRUE(instance.IsPreInstalledApex(*apex1));
264 
265   // It's same apex, but path is different. Shouldn't be treated as
266   // pre-installed.
267   auto apex2 = ApexFile::Open(GetTestFile("apex.apexd_test.apex"));
268   ASSERT_TRUE(IsOk(apex2));
269   ASSERT_FALSE(instance.IsPreInstalledApex(*apex2));
270 
271   auto apex3 =
272       ApexFile::Open(GetTestFile("apex.apexd_test_different_app.apex"));
273   ASSERT_TRUE(IsOk(apex3));
274   ASSERT_FALSE(instance.IsPreInstalledApex(*apex3));
275 }
276 
TEST(ApexFileRepositoryTest,IsDecompressedApex)277 TEST(ApexFileRepositoryTest, IsDecompressedApex) {
278   // Prepare instance
279   TemporaryDir decompression_dir;
280   ApexFileRepository instance(decompression_dir.path);
281 
282   // Prepare decompressed apex
283   std::string filename = "com.android.apex.compressed.v1_original.apex";
284   fs::copy(GetTestFile(filename), decompression_dir.path);
285   auto decompressed_path =
286       StringPrintf("%s/%s", decompression_dir.path, filename.c_str());
287   auto decompressed_apex = ApexFile::Open(decompressed_path);
288 
289   // Any file which is already located in |decompression_dir| should be
290   // considered decompressed
291   ASSERT_TRUE(instance.IsDecompressedApex(*decompressed_apex));
292 
293   // Hard links with same file name is not considered decompressed
294   TemporaryDir active_dir;
295   auto active_path = StringPrintf("%s/%s", active_dir.path, filename.c_str());
296   std::error_code ec;
297   fs::create_hard_link(decompressed_path, active_path, ec);
298   ASSERT_FALSE(ec) << "Failed to create hardlink";
299   auto active_apex = ApexFile::Open(active_path);
300   ASSERT_FALSE(instance.IsDecompressedApex(*active_apex));
301 }
302 
TEST(ApexFileRepositoryTest,AddAndGetDataApex)303 TEST(ApexFileRepositoryTest, AddAndGetDataApex) {
304   // Prepare test data.
305   TemporaryDir built_in_dir, data_dir, decompression_dir;
306   fs::copy(GetTestFile("apex.apexd_test.apex"), built_in_dir.path);
307   fs::copy(GetTestFile("apex.apexd_test_v2.apex"), data_dir.path);
308   PrepareCompressedApex("com.android.apex.compressed.v1.capex",
309                         built_in_dir.path, decompression_dir.path);
310   // Add a data apex that has kDecompressedApexPackageSuffix
311   fs::copy(GetTestFile("com.android.apex.compressed.v1_original.apex"),
312            StringPrintf("%s/com.android.apex.compressed@1%s", data_dir.path,
313                         kDecompressedApexPackageSuffix));
314 
315   ApexFileRepository instance(decompression_dir.path);
316   ASSERT_TRUE(IsOk(instance.AddPreInstalledApex({built_in_dir.path})));
317   ASSERT_TRUE(IsOk(instance.AddDataApex(data_dir.path)));
318 
319   // ApexFileRepository should only deal with APEX in /data/apex/active.
320   // Decompressed APEX should not be included
321   auto data_apexs = instance.GetDataApexFiles();
322   auto normal_apex =
323       ApexFile::Open(StringPrintf("%s/apex.apexd_test_v2.apex", data_dir.path));
324   ASSERT_THAT(data_apexs,
325               UnorderedElementsAre(ApexFileEq(ByRef(*normal_apex))));
326 }
327 
TEST(ApexFileRepositoryTest,AddDataApexIgnoreCompressedApex)328 TEST(ApexFileRepositoryTest, AddDataApexIgnoreCompressedApex) {
329   // Prepare test data.
330   TemporaryDir data_dir, decompression_dir;
331   fs::copy(GetTestFile("com.android.apex.compressed.v1.capex"), data_dir.path);
332 
333   ApexFileRepository instance;
334   ASSERT_TRUE(IsOk(instance.AddDataApex(data_dir.path)));
335 
336   auto data_apexs = instance.GetDataApexFiles();
337   ASSERT_EQ(data_apexs.size(), 0u);
338 }
339 
TEST(ApexFileRepositoryTest,AddDataApexIgnoreIfNotPreInstalled)340 TEST(ApexFileRepositoryTest, AddDataApexIgnoreIfNotPreInstalled) {
341   // Prepare test data.
342   TemporaryDir data_dir, decompression_dir;
343   fs::copy(GetTestFile("apex.apexd_test.apex"), data_dir.path);
344 
345   ApexFileRepository instance;
346   ASSERT_TRUE(IsOk(instance.AddDataApex(data_dir.path)));
347 
348   auto data_apexs = instance.GetDataApexFiles();
349   ASSERT_EQ(data_apexs.size(), 0u);
350 }
351 
TEST(ApexFileRepositoryTest,AddDataApexPrioritizeHigherVersionApex)352 TEST(ApexFileRepositoryTest, AddDataApexPrioritizeHigherVersionApex) {
353   // Prepare test data.
354   TemporaryDir built_in_dir, data_dir, decompression_dir;
355   fs::copy(GetTestFile("apex.apexd_test.apex"), built_in_dir.path);
356   fs::copy(GetTestFile("apex.apexd_test.apex"), data_dir.path);
357   fs::copy(GetTestFile("apex.apexd_test_v2.apex"), data_dir.path);
358 
359   ApexFileRepository instance;
360   ASSERT_TRUE(IsOk(instance.AddPreInstalledApex({built_in_dir.path})));
361   ASSERT_TRUE(IsOk(instance.AddDataApex(data_dir.path)));
362 
363   auto data_apexs = instance.GetDataApexFiles();
364   auto normal_apex =
365       ApexFile::Open(StringPrintf("%s/apex.apexd_test_v2.apex", data_dir.path));
366   ASSERT_THAT(data_apexs,
367               UnorderedElementsAre(ApexFileEq(ByRef(*normal_apex))));
368 }
369 
TEST(ApexFileRepositoryTest,AddDataApexDoesNotScanDecompressedApex)370 TEST(ApexFileRepositoryTest, AddDataApexDoesNotScanDecompressedApex) {
371   // Prepare test data.
372   TemporaryDir built_in_dir, data_dir, decompression_dir;
373   PrepareCompressedApex("com.android.apex.compressed.v1.capex",
374                         built_in_dir.path, decompression_dir.path);
375 
376   ApexFileRepository instance(decompression_dir.path);
377   ASSERT_TRUE(IsOk(instance.AddPreInstalledApex({built_in_dir.path})));
378   ASSERT_TRUE(IsOk(instance.AddDataApex(data_dir.path)));
379 
380   auto data_apexs = instance.GetDataApexFiles();
381   ASSERT_EQ(data_apexs.size(), 0u);
382 }
383 
TEST(ApexFileRepositoryTest,AddDataApexIgnoreWrongPublicKey)384 TEST(ApexFileRepositoryTest, AddDataApexIgnoreWrongPublicKey) {
385   // Prepare test data.
386   TemporaryDir built_in_dir, data_dir, decompression_dir;
387   fs::copy(GetTestFile("apex.apexd_test.apex"), built_in_dir.path);
388   fs::copy(GetTestFile("apex.apexd_test_different_key.apex"), data_dir.path);
389 
390   ApexFileRepository instance;
391   ASSERT_TRUE(IsOk(instance.AddPreInstalledApex({built_in_dir.path})));
392   ASSERT_TRUE(IsOk(instance.AddDataApex(data_dir.path)));
393 
394   auto data_apexs = instance.GetDataApexFiles();
395   ASSERT_EQ(data_apexs.size(), 0u);
396 }
397 
TEST(ApexFileRepositoryTest,GetPreInstalledApexFiles)398 TEST(ApexFileRepositoryTest, GetPreInstalledApexFiles) {
399   // Prepare test data.
400   TemporaryDir built_in_dir;
401   fs::copy(GetTestFile("apex.apexd_test.apex"), built_in_dir.path);
402   fs::copy(GetTestFile("com.android.apex.compressed.v1.capex"),
403            built_in_dir.path);
404 
405   ApexFileRepository instance;
406   ASSERT_TRUE(IsOk(instance.AddPreInstalledApex({built_in_dir.path})));
407 
408   auto pre_installed_apexs = instance.GetPreInstalledApexFiles();
409   auto pre_apex_1 = ApexFile::Open(
410       StringPrintf("%s/apex.apexd_test.apex", built_in_dir.path));
411   auto pre_apex_2 = ApexFile::Open(StringPrintf(
412       "%s/com.android.apex.compressed.v1.capex", built_in_dir.path));
413   ASSERT_THAT(pre_installed_apexs,
414               UnorderedElementsAre(ApexFileEq(ByRef(*pre_apex_1)),
415                                    ApexFileEq(ByRef(*pre_apex_2))));
416 }
417 
TEST(ApexFileRepositoryTest,AllApexFilesByName)418 TEST(ApexFileRepositoryTest, AllApexFilesByName) {
419   TemporaryDir built_in_dir, decompression_dir;
420   fs::copy(GetTestFile("apex.apexd_test.apex"), built_in_dir.path);
421   fs::copy(GetTestFile("com.android.apex.cts.shim.apex"), built_in_dir.path);
422   fs::copy(GetTestFile("com.android.apex.compressed.v1.capex"),
423            built_in_dir.path);
424   ApexFileRepository instance;
425   ASSERT_TRUE(IsOk(instance.AddPreInstalledApex({built_in_dir.path})));
426 
427   TemporaryDir data_dir;
428   fs::copy(GetTestFile("com.android.apex.cts.shim.v2.apex"), data_dir.path);
429   ASSERT_TRUE(IsOk(instance.AddDataApex(data_dir.path)));
430 
431   auto result = instance.AllApexFilesByName();
432 
433   // Verify the contents of result
434   auto apexd_test_file = ApexFile::Open(
435       StringPrintf("%s/apex.apexd_test.apex", built_in_dir.path));
436   auto shim_v1 = ApexFile::Open(
437       StringPrintf("%s/com.android.apex.cts.shim.apex", built_in_dir.path));
438   auto compressed_apex = ApexFile::Open(StringPrintf(
439       "%s/com.android.apex.compressed.v1.capex", built_in_dir.path));
440   auto shim_v2 = ApexFile::Open(
441       StringPrintf("%s/com.android.apex.cts.shim.v2.apex", data_dir.path));
442 
443   ASSERT_EQ(result.size(), 3u);
444   ASSERT_THAT(result[apexd_test_file->GetManifest().name()],
445               UnorderedElementsAre(ApexFileEq(ByRef(*apexd_test_file))));
446   ASSERT_THAT(result[shim_v1->GetManifest().name()],
447               UnorderedElementsAre(ApexFileEq(ByRef(*shim_v1)),
448                                    ApexFileEq(ByRef(*shim_v2))));
449   ASSERT_THAT(result[compressed_apex->GetManifest().name()],
450               UnorderedElementsAre(ApexFileEq(ByRef(*compressed_apex))));
451 }
452 
TEST(ApexFileRepositoryTest,GetDataApex)453 TEST(ApexFileRepositoryTest, GetDataApex) {
454   // Prepare test data.
455   TemporaryDir built_in_dir, data_dir;
456   fs::copy(GetTestFile("apex.apexd_test.apex"), built_in_dir.path);
457   fs::copy(GetTestFile("apex.apexd_test_v2.apex"), data_dir.path);
458 
459   ApexFileRepository instance;
460   ASSERT_TRUE(IsOk(instance.AddPreInstalledApex({built_in_dir.path})));
461   ASSERT_TRUE(IsOk(instance.AddDataApex(data_dir.path)));
462 
463   auto apex =
464       ApexFile::Open(StringPrintf("%s/apex.apexd_test_v2.apex", data_dir.path));
465   ASSERT_RESULT_OK(apex);
466 
467   auto ret = instance.GetDataApex("com.android.apex.test_package");
468   ASSERT_THAT(ret, ApexFileEq(ByRef(*apex)));
469 }
470 
TEST(ApexFileRepositoryTest,GetDataApexNoSuchApexAborts)471 TEST(ApexFileRepositoryTest, GetDataApexNoSuchApexAborts) {
472   ASSERT_DEATH(
473       {
474         ApexFileRepository instance;
475         instance.GetDataApex("whatever");
476       },
477       "");
478 }
479 
TEST(ApexFileRepositoryTest,GetPreInstalledApex)480 TEST(ApexFileRepositoryTest, GetPreInstalledApex) {
481   // Prepare test data.
482   TemporaryDir built_in_dir;
483   fs::copy(GetTestFile("apex.apexd_test.apex"), built_in_dir.path);
484 
485   ApexFileRepository instance;
486   ASSERT_TRUE(IsOk(instance.AddPreInstalledApex({built_in_dir.path})));
487 
488   auto apex = ApexFile::Open(
489       StringPrintf("%s/apex.apexd_test.apex", built_in_dir.path));
490   ASSERT_RESULT_OK(apex);
491 
492   auto ret = instance.GetPreInstalledApex("com.android.apex.test_package");
493   ASSERT_THAT(ret, ApexFileEq(ByRef(*apex)));
494 }
495 
TEST(ApexFileRepositoryTest,GetPreInstalledApexNoSuchApexAborts)496 TEST(ApexFileRepositoryTest, GetPreInstalledApexNoSuchApexAborts) {
497   ASSERT_DEATH(
498       {
499         ApexFileRepository instance;
500         instance.GetPreInstalledApex("whatever");
501       },
502       "");
503 }
504 
505 }  // namespace apex
506 }  // namespace android
507