1 /*
2  * Copyright (C) 2019 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 "patch_utils.h"
18 
19 #include <android-base/file.h>
20 #include <gtest/gtest.h>
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <sstream>
24 #include <string>
25 
26 #include "adb_io.h"
27 #include "sysdeps.h"
28 
29 using namespace com::android::fastdeploy;
30 
GetTestFile(const std::string & name)31 static std::string GetTestFile(const std::string& name) {
32     return "fastdeploy/testdata/" + name;
33 }
34 
FileMatchesContent(android::base::borrowed_fd input,const char * contents,ssize_t contentsSize)35 bool FileMatchesContent(android::base::borrowed_fd input, const char* contents,
36                         ssize_t contentsSize) {
37     adb_lseek(input, 0, SEEK_SET);
38     // Use a temp buffer larger than any test contents.
39     constexpr int BUFFER_SIZE = 2048;
40     char buffer[BUFFER_SIZE];
41     bool result = true;
42     // Validate size of files is equal.
43     ssize_t readAmount = adb_read(input, buffer, BUFFER_SIZE);
44     EXPECT_EQ(readAmount, contentsSize);
45     result = memcmp(buffer, contents, readAmount) == 0;
46     for (int i = 0; i < readAmount; i++) {
47         printf("%x", buffer[i]);
48     }
49     printf(" == ");
50     for (int i = 0; i < contentsSize; i++) {
51         printf("%x", contents[i]);
52     }
53     printf("\n");
54 
55     return result;
56 }
57 
TEST(PatchUtilsTest,SwapLongWrites)58 TEST(PatchUtilsTest, SwapLongWrites) {
59     TemporaryFile output;
60     PatchUtils::WriteLong(0x0011223344556677, output.fd);
61     adb_lseek(output.fd, 0, SEEK_SET);
62     const char expected[] = {0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11, 0x00};
63     EXPECT_TRUE(FileMatchesContent(output.fd, expected, 8));
64 }
65 
TEST(PatchUtilsTest,PipeWritesAmountToOutput)66 TEST(PatchUtilsTest, PipeWritesAmountToOutput) {
67     std::string expected("Some Data");
68     TemporaryFile input;
69     TemporaryFile output;
70     // Populate input file.
71     WriteFdExactly(input.fd, expected);
72     adb_lseek(input.fd, 0, SEEK_SET);
73     // Open input file for read, and output file for write.
74     PatchUtils::Pipe(input.fd, output.fd, expected.size());
75     // Validate pipe worked
76     EXPECT_TRUE(FileMatchesContent(output.fd, expected.c_str(), expected.size()));
77 }
78 
TEST(PatchUtilsTest,SignatureConstMatches)79 TEST(PatchUtilsTest, SignatureConstMatches) {
80     std::string apkFile = GetTestFile("rotating_cube-release.apk");
81     TemporaryFile output;
82     PatchUtils::WriteSignature(output.fd);
83     std::string contents("FASTDEPLOY");
84     EXPECT_TRUE(FileMatchesContent(output.fd, contents.c_str(), contents.size()));
85 }
86 
TEST(PatchUtilsTest,GatherMetadata)87 TEST(PatchUtilsTest, GatherMetadata) {
88     std::string apkFile = GetTestFile("rotating_cube-release.apk");
89     APKMetaData actual = PatchUtils::GetHostAPKMetaData(apkFile.c_str());
90 
91     std::string expectedMetadata;
92     android::base::ReadFileToString(GetTestFile("rotating_cube-metadata-release.data"),
93                                     &expectedMetadata, true);
94     APKMetaData expected;
95     EXPECT_TRUE(expected.ParseFromString(expectedMetadata));
96 
97     // Test paths might vary.
98     expected.set_absolute_path(actual.absolute_path());
99 
100     std::string actualMetadata;
101     actual.SerializeToString(&actualMetadata);
102 
103     expected.SerializeToString(&expectedMetadata);
104 
105     EXPECT_EQ(expectedMetadata, actualMetadata);
106 }
107 
sanitize(APKMetaData & metadata)108 static inline void sanitize(APKMetaData& metadata) {
109     metadata.clear_absolute_path();
110     for (auto&& entry : *metadata.mutable_entries()) {
111         entry.clear_datasize();
112     }
113 }
114 
TEST(PatchUtilsTest,GatherDumpMetadata)115 TEST(PatchUtilsTest, GatherDumpMetadata) {
116     APKMetaData hostMetadata;
117     APKMetaData deviceMetadata;
118 
119     hostMetadata = PatchUtils::GetHostAPKMetaData(GetTestFile("sample.apk").c_str());
120 
121     {
122         std::string cd;
123         android::base::ReadFileToString(GetTestFile("sample.cd"), &cd, true);
124 
125         APKDump dump;
126         dump.set_cd(std::move(cd));
127 
128         deviceMetadata = PatchUtils::GetDeviceAPKMetaData(dump);
129     }
130 
131     sanitize(hostMetadata);
132     sanitize(deviceMetadata);
133 
134     std::string expectedMetadata;
135     hostMetadata.SerializeToString(&expectedMetadata);
136 
137     std::string actualMetadata;
138     deviceMetadata.SerializeToString(&actualMetadata);
139 
140     EXPECT_EQ(expectedMetadata, actualMetadata);
141 }
142