Home | History | Annotate | Download | only in tests
      1 /*
      2  * Copyright (C) 2017 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 <stdlib.h>
     18 #include <string.h>
     19 #include <sys/statvfs.h>
     20 #include <sys/xattr.h>
     21 
     22 #include <android-base/logging.h>
     23 #include <android-base/stringprintf.h>
     24 #include <cutils/properties.h>
     25 #include <gtest/gtest.h>
     26 
     27 #include "InstalldNativeService.h"
     28 #include "globals.h"
     29 #include "utils.h"
     30 
     31 using android::base::StringPrintf;
     32 
     33 namespace android {
     34 namespace installd {
     35 
     36 constexpr const char* kTestUuid = "TEST";
     37 
     38 constexpr int64_t kKbInBytes = 1024;
     39 constexpr int64_t kMbInBytes = 1024 * kKbInBytes;
     40 constexpr int64_t kGbInBytes = 1024 * kMbInBytes;
     41 constexpr int64_t kTbInBytes = 1024 * kGbInBytes;
     42 
     43 static constexpr int FLAG_FREE_CACHE_V2 = 1 << 13;
     44 static constexpr int FLAG_FREE_CACHE_V2_DEFY_QUOTA = 1 << 14;
     45 
     46 int get_property(const char *key, char *value, const char *default_value) {
     47     return property_get(key, value, default_value);
     48 }
     49 
     50 bool calculate_oat_file_path(char path[PKG_PATH_MAX] ATTRIBUTE_UNUSED,
     51         const char *oat_dir ATTRIBUTE_UNUSED,
     52         const char *apk_path ATTRIBUTE_UNUSED,
     53         const char *instruction_set ATTRIBUTE_UNUSED) {
     54     return false;
     55 }
     56 
     57 bool calculate_odex_file_path(char path[PKG_PATH_MAX] ATTRIBUTE_UNUSED,
     58         const char *apk_path ATTRIBUTE_UNUSED,
     59         const char *instruction_set ATTRIBUTE_UNUSED) {
     60     return false;
     61 }
     62 
     63 bool create_cache_path(char path[PKG_PATH_MAX] ATTRIBUTE_UNUSED,
     64         const char *src ATTRIBUTE_UNUSED,
     65         const char *instruction_set ATTRIBUTE_UNUSED) {
     66     return false;
     67 }
     68 
     69 static void mkdir(const char* path) {
     70     const char* fullPath = StringPrintf("/data/local/tmp/user/0/%s", path).c_str();
     71     ::mkdir(fullPath, 0755);
     72 }
     73 
     74 static void touch(const char* path, int len, int time) {
     75     const char* fullPath = StringPrintf("/data/local/tmp/user/0/%s", path).c_str();
     76     int fd = ::open(fullPath, O_RDWR | O_CREAT, 0644);
     77     ::fallocate(fd, 0, 0, len);
     78     ::close(fd);
     79     struct utimbuf times;
     80     times.actime = times.modtime = std::time(0) + time;
     81     ::utime(fullPath, &times);
     82 }
     83 
     84 static int exists(const char* path) {
     85     const char* fullPath = StringPrintf("/data/local/tmp/user/0/%s", path).c_str();
     86     return ::access(fullPath, F_OK);
     87 }
     88 
     89 static int64_t size(const char* path) {
     90     const char* fullPath = StringPrintf("/data/local/tmp/user/0/%s", path).c_str();
     91     struct stat buf;
     92     if (!stat(fullPath, &buf)) {
     93         return buf.st_size;
     94     } else {
     95         return -1;
     96     }
     97 }
     98 
     99 static int64_t free() {
    100     struct statvfs buf;
    101     if (!statvfs("/data/local/tmp", &buf)) {
    102         return static_cast<int64_t>(buf.f_bavail) * buf.f_frsize;
    103     } else {
    104         PLOG(ERROR) << "Failed to statvfs";
    105         return -1;
    106     }
    107 }
    108 
    109 static void setxattr(const char* path, const char* key) {
    110     const char* fullPath = StringPrintf("/data/local/tmp/user/0/%s", path).c_str();
    111     ::setxattr(fullPath, key, "", 0, 0);
    112 }
    113 
    114 class CacheTest : public testing::Test {
    115 protected:
    116     InstalldNativeService* service;
    117     std::unique_ptr<std::string> testUuid;
    118 
    119     virtual void SetUp() {
    120         setenv("ANDROID_LOG_TAGS", "*:v", 1);
    121         android::base::InitLogging(nullptr);
    122 
    123         service = new InstalldNativeService();
    124         testUuid = std::make_unique<std::string>();
    125         *testUuid = std::string(kTestUuid);
    126         system("mkdir -p /data/local/tmp/user/0");
    127     }
    128 
    129     virtual void TearDown() {
    130         delete service;
    131         system("rm -rf /data/local/tmp/user");
    132     }
    133 };
    134 
    135 TEST_F(CacheTest, FreeCache_All) {
    136     LOG(INFO) << "FreeCache_All";
    137 
    138     mkdir("com.example");
    139     touch("com.example/normal", 1 * kMbInBytes, 60);
    140     mkdir("com.example/cache");
    141     mkdir("com.example/cache/foo");
    142     touch("com.example/cache/foo/one", 1 * kMbInBytes, 60);
    143     touch("com.example/cache/foo/two", 2 * kMbInBytes, 120);
    144 
    145     EXPECT_EQ(0, exists("com.example/normal"));
    146     EXPECT_EQ(0, exists("com.example/cache/foo/one"));
    147     EXPECT_EQ(0, exists("com.example/cache/foo/two"));
    148 
    149     service->freeCache(testUuid, kTbInBytes, 0,
    150             FLAG_FREE_CACHE_V2 | FLAG_FREE_CACHE_V2_DEFY_QUOTA);
    151 
    152     EXPECT_EQ(0, exists("com.example/normal"));
    153     EXPECT_EQ(-1, exists("com.example/cache/foo/one"));
    154     EXPECT_EQ(-1, exists("com.example/cache/foo/two"));
    155 }
    156 
    157 TEST_F(CacheTest, FreeCache_Age) {
    158     LOG(INFO) << "FreeCache_Age";
    159 
    160     mkdir("com.example");
    161     mkdir("com.example/cache");
    162     mkdir("com.example/cache/foo");
    163     touch("com.example/cache/foo/one", kMbInBytes, 60);
    164     touch("com.example/cache/foo/two", kMbInBytes, 120);
    165 
    166     service->freeCache(testUuid, free() + kKbInBytes, 0,
    167             FLAG_FREE_CACHE_V2 | FLAG_FREE_CACHE_V2_DEFY_QUOTA);
    168 
    169     EXPECT_EQ(-1, exists("com.example/cache/foo/one"));
    170     EXPECT_EQ(0, exists("com.example/cache/foo/two"));
    171 
    172     service->freeCache(testUuid, free() + kKbInBytes, 0,
    173             FLAG_FREE_CACHE_V2 | FLAG_FREE_CACHE_V2_DEFY_QUOTA);
    174 
    175     EXPECT_EQ(-1, exists("com.example/cache/foo/one"));
    176     EXPECT_EQ(-1, exists("com.example/cache/foo/two"));
    177 }
    178 
    179 TEST_F(CacheTest, FreeCache_Tombstone) {
    180     LOG(INFO) << "FreeCache_Tombstone";
    181 
    182     mkdir("com.example");
    183     mkdir("com.example/cache");
    184     mkdir("com.example/cache/foo");
    185     touch("com.example/cache/foo/foo1", 1 * kMbInBytes, 60);
    186     touch("com.example/cache/foo/foo2", 1 * kMbInBytes, 60);
    187     mkdir("com.example/cache/bar");
    188     touch("com.example/cache/bar/bar1", 2 * kMbInBytes, 120);
    189     touch("com.example/cache/bar/bar2", 2 * kMbInBytes, 120);
    190 
    191     setxattr("com.example/cache/bar", "user.cache_tombstone");
    192 
    193     EXPECT_EQ(0, exists("com.example/cache/foo/foo1"));
    194     EXPECT_EQ(0, exists("com.example/cache/foo/foo2"));
    195     EXPECT_EQ(0, exists("com.example/cache/bar/bar1"));
    196     EXPECT_EQ(0, exists("com.example/cache/bar/bar2"));
    197     EXPECT_EQ(2 * kMbInBytes, size("com.example/cache/bar/bar1"));
    198     EXPECT_EQ(2 * kMbInBytes, size("com.example/cache/bar/bar2"));
    199 
    200     service->freeCache(testUuid, kTbInBytes, 0,
    201             FLAG_FREE_CACHE_V2 | FLAG_FREE_CACHE_V2_DEFY_QUOTA);
    202 
    203     EXPECT_EQ(-1, exists("com.example/cache/foo/foo1"));
    204     EXPECT_EQ(-1, exists("com.example/cache/foo/foo2"));
    205     EXPECT_EQ(0, exists("com.example/cache/bar/bar1"));
    206     EXPECT_EQ(0, exists("com.example/cache/bar/bar2"));
    207     EXPECT_EQ(0, size("com.example/cache/bar/bar1"));
    208     EXPECT_EQ(0, size("com.example/cache/bar/bar2"));
    209 }
    210 
    211 TEST_F(CacheTest, FreeCache_Group) {
    212     LOG(INFO) << "FreeCache_Group";
    213 
    214     mkdir("com.example");
    215     mkdir("com.example/cache");
    216     mkdir("com.example/cache/foo");
    217     touch("com.example/cache/foo/foo1", 1 * kMbInBytes, 60);
    218     touch("com.example/cache/foo/foo2", 1 * kMbInBytes, 120);
    219 
    220     setxattr("com.example/cache/foo", "user.cache_group");
    221 
    222     service->freeCache(testUuid, free() + kKbInBytes, 0,
    223             FLAG_FREE_CACHE_V2 | FLAG_FREE_CACHE_V2_DEFY_QUOTA);
    224 
    225     EXPECT_EQ(-1, exists("com.example/cache/foo/foo1"));
    226     EXPECT_EQ(-1, exists("com.example/cache/foo/foo2"));
    227 }
    228 
    229 TEST_F(CacheTest, FreeCache_GroupTombstone) {
    230     LOG(INFO) << "FreeCache_GroupTombstone";
    231 
    232     mkdir("com.example");
    233     mkdir("com.example/cache");
    234 
    235     // this dir must look really old for some reason?
    236     mkdir("com.example/cache/group");
    237     touch("com.example/cache/group/file1", kMbInBytes, 120);
    238     touch("com.example/cache/group/file2", kMbInBytes, 120);
    239     mkdir("com.example/cache/group/dir");
    240     touch("com.example/cache/group/dir/file1", kMbInBytes, 120);
    241     touch("com.example/cache/group/dir/file2", kMbInBytes, 120);
    242     mkdir("com.example/cache/group/tomb");
    243     touch("com.example/cache/group/tomb/file1", kMbInBytes, 120);
    244     touch("com.example/cache/group/tomb/file2", kMbInBytes, 120);
    245     mkdir("com.example/cache/group/tomb/dir");
    246     touch("com.example/cache/group/tomb/dir/file1", kMbInBytes, 120);
    247     touch("com.example/cache/group/tomb/dir/file2", kMbInBytes, 120);
    248 
    249     mkdir("com.example/cache/tomb");
    250     touch("com.example/cache/tomb/file1", kMbInBytes, 240);
    251     touch("com.example/cache/tomb/file2", kMbInBytes, 240);
    252     mkdir("com.example/cache/tomb/dir");
    253     touch("com.example/cache/tomb/dir/file1", kMbInBytes, 240);
    254     touch("com.example/cache/tomb/dir/file2", kMbInBytes, 240);
    255     mkdir("com.example/cache/tomb/group");
    256     touch("com.example/cache/tomb/group/file1", kMbInBytes, 60);
    257     touch("com.example/cache/tomb/group/file2", kMbInBytes, 60);
    258     mkdir("com.example/cache/tomb/group/dir");
    259     touch("com.example/cache/tomb/group/dir/file1", kMbInBytes, 60);
    260     touch("com.example/cache/tomb/group/dir/file2", kMbInBytes, 60);
    261 
    262     setxattr("com.example/cache/group", "user.cache_group");
    263     setxattr("com.example/cache/group/tomb", "user.cache_tombstone");
    264     setxattr("com.example/cache/tomb", "user.cache_tombstone");
    265     setxattr("com.example/cache/tomb/group", "user.cache_group");
    266 
    267     service->freeCache(testUuid, free() + kKbInBytes, 0,
    268             FLAG_FREE_CACHE_V2 | FLAG_FREE_CACHE_V2_DEFY_QUOTA);
    269 
    270     EXPECT_EQ(kMbInBytes, size("com.example/cache/group/file1"));
    271     EXPECT_EQ(kMbInBytes, size("com.example/cache/group/file2"));
    272     EXPECT_EQ(kMbInBytes, size("com.example/cache/group/dir/file1"));
    273     EXPECT_EQ(kMbInBytes, size("com.example/cache/group/dir/file2"));
    274     EXPECT_EQ(kMbInBytes, size("com.example/cache/group/tomb/file1"));
    275     EXPECT_EQ(kMbInBytes, size("com.example/cache/group/tomb/file2"));
    276     EXPECT_EQ(kMbInBytes, size("com.example/cache/group/tomb/dir/file1"));
    277     EXPECT_EQ(kMbInBytes, size("com.example/cache/group/tomb/dir/file2"));
    278 
    279     EXPECT_EQ(kMbInBytes, size("com.example/cache/tomb/file1"));
    280     EXPECT_EQ(kMbInBytes, size("com.example/cache/tomb/file2"));
    281     EXPECT_EQ(kMbInBytes, size("com.example/cache/tomb/dir/file1"));
    282     EXPECT_EQ(kMbInBytes, size("com.example/cache/tomb/dir/file2"));
    283     EXPECT_EQ(0, size("com.example/cache/tomb/group/file1"));
    284     EXPECT_EQ(0, size("com.example/cache/tomb/group/file2"));
    285     EXPECT_EQ(0, size("com.example/cache/tomb/group/dir/file1"));
    286     EXPECT_EQ(0, size("com.example/cache/tomb/group/dir/file2"));
    287 
    288     service->freeCache(testUuid, free() + kKbInBytes, 0,
    289             FLAG_FREE_CACHE_V2 | FLAG_FREE_CACHE_V2_DEFY_QUOTA);
    290 
    291     EXPECT_EQ(-1, size("com.example/cache/group/file1"));
    292     EXPECT_EQ(-1, size("com.example/cache/group/file2"));
    293     EXPECT_EQ(-1, size("com.example/cache/group/dir/file1"));
    294     EXPECT_EQ(-1, size("com.example/cache/group/dir/file2"));
    295     EXPECT_EQ(0, size("com.example/cache/group/tomb/file1"));
    296     EXPECT_EQ(0, size("com.example/cache/group/tomb/file2"));
    297     EXPECT_EQ(0, size("com.example/cache/group/tomb/dir/file1"));
    298     EXPECT_EQ(0, size("com.example/cache/group/tomb/dir/file2"));
    299 
    300     EXPECT_EQ(kMbInBytes, size("com.example/cache/tomb/file1"));
    301     EXPECT_EQ(kMbInBytes, size("com.example/cache/tomb/file2"));
    302     EXPECT_EQ(kMbInBytes, size("com.example/cache/tomb/dir/file1"));
    303     EXPECT_EQ(kMbInBytes, size("com.example/cache/tomb/dir/file2"));
    304     EXPECT_EQ(0, size("com.example/cache/tomb/group/file1"));
    305     EXPECT_EQ(0, size("com.example/cache/tomb/group/file2"));
    306     EXPECT_EQ(0, size("com.example/cache/tomb/group/dir/file1"));
    307     EXPECT_EQ(0, size("com.example/cache/tomb/group/dir/file2"));
    308 
    309     service->freeCache(testUuid, kTbInBytes, 0,
    310             FLAG_FREE_CACHE_V2 | FLAG_FREE_CACHE_V2_DEFY_QUOTA);
    311 
    312     EXPECT_EQ(-1, size("com.example/cache/group/file1"));
    313     EXPECT_EQ(-1, size("com.example/cache/group/file2"));
    314     EXPECT_EQ(-1, size("com.example/cache/group/dir/file1"));
    315     EXPECT_EQ(-1, size("com.example/cache/group/dir/file2"));
    316     EXPECT_EQ(0, size("com.example/cache/group/tomb/file1"));
    317     EXPECT_EQ(0, size("com.example/cache/group/tomb/file2"));
    318     EXPECT_EQ(0, size("com.example/cache/group/tomb/dir/file1"));
    319     EXPECT_EQ(0, size("com.example/cache/group/tomb/dir/file2"));
    320 
    321     EXPECT_EQ(0, size("com.example/cache/tomb/file1"));
    322     EXPECT_EQ(0, size("com.example/cache/tomb/file2"));
    323     EXPECT_EQ(0, size("com.example/cache/tomb/dir/file1"));
    324     EXPECT_EQ(0, size("com.example/cache/tomb/dir/file2"));
    325     EXPECT_EQ(0, size("com.example/cache/tomb/group/file1"));
    326     EXPECT_EQ(0, size("com.example/cache/tomb/group/file2"));
    327     EXPECT_EQ(0, size("com.example/cache/tomb/group/dir/file1"));
    328     EXPECT_EQ(0, size("com.example/cache/tomb/group/dir/file2"));
    329 }
    330 
    331 }  // namespace installd
    332 }  // namespace android
    333