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 static constexpr int FLAG_FORCE = 1 << 16;
     39 
     40 int get_property(const char *key, char *value, const char *default_value) {
     41     return property_get(key, value, default_value);
     42 }
     43 
     44 bool calculate_oat_file_path(char path[PKG_PATH_MAX] ATTRIBUTE_UNUSED,
     45         const char *oat_dir ATTRIBUTE_UNUSED,
     46         const char *apk_path ATTRIBUTE_UNUSED,
     47         const char *instruction_set ATTRIBUTE_UNUSED) {
     48     return false;
     49 }
     50 
     51 bool calculate_odex_file_path(char path[PKG_PATH_MAX] ATTRIBUTE_UNUSED,
     52         const char *apk_path ATTRIBUTE_UNUSED,
     53         const char *instruction_set ATTRIBUTE_UNUSED) {
     54     return false;
     55 }
     56 
     57 bool create_cache_path(char path[PKG_PATH_MAX],
     58         const char *src,
     59         const char *instruction_set) {
     60     // Not really a valid path but it's good enough for testing.
     61     sprintf(path,"/data/dalvik-cache/%s/%s", instruction_set, src);
     62     return true;
     63 }
     64 
     65 static void mkdir(const char* path, uid_t owner, gid_t group, mode_t mode) {
     66     const char* fullPath = StringPrintf("/data/local/tmp/user/0/%s", path).c_str();
     67     ::mkdir(fullPath, mode);
     68     ::chown(fullPath, owner, group);
     69     ::chmod(fullPath, mode);
     70 }
     71 
     72 static void touch(const char* path, uid_t owner, gid_t group, mode_t mode) {
     73     int fd = ::open(StringPrintf("/data/local/tmp/user/0/%s", path).c_str(),
     74             O_RDWR | O_CREAT, mode);
     75     ::fchown(fd, owner, group);
     76     ::fchmod(fd, mode);
     77     ::close(fd);
     78 }
     79 
     80 static int stat_gid(const char* path) {
     81     struct stat buf;
     82     ::stat(StringPrintf("/data/local/tmp/user/0/%s", path).c_str(), &buf);
     83     return buf.st_gid;
     84 }
     85 
     86 static int stat_mode(const char* path) {
     87     struct stat buf;
     88     ::stat(StringPrintf("/data/local/tmp/user/0/%s", path).c_str(), &buf);
     89     return buf.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO | S_ISGID);
     90 }
     91 
     92 class ServiceTest : public testing::Test {
     93 protected:
     94     InstalldNativeService* service;
     95     std::unique_ptr<std::string> testUuid;
     96 
     97     virtual void SetUp() {
     98         setenv("ANDROID_LOG_TAGS", "*:v", 1);
     99         android::base::InitLogging(nullptr);
    100 
    101         service = new InstalldNativeService();
    102         testUuid = std::make_unique<std::string>();
    103         *testUuid = std::string(kTestUuid);
    104         system("mkdir -p /data/local/tmp/user/0");
    105     }
    106 
    107     virtual void TearDown() {
    108         delete service;
    109         system("rm -rf /data/local/tmp/user");
    110     }
    111 };
    112 
    113 TEST_F(ServiceTest, FixupAppData_Upgrade) {
    114     LOG(INFO) << "FixupAppData_Upgrade";
    115 
    116     mkdir("com.example", 10000, 10000, 0700);
    117     mkdir("com.example/normal", 10000, 10000, 0700);
    118     mkdir("com.example/cache", 10000, 10000, 0700);
    119     touch("com.example/cache/file", 10000, 10000, 0700);
    120 
    121     service->fixupAppData(testUuid, 0);
    122 
    123     EXPECT_EQ(10000, stat_gid("com.example/normal"));
    124     EXPECT_EQ(20000, stat_gid("com.example/cache"));
    125     EXPECT_EQ(20000, stat_gid("com.example/cache/file"));
    126 
    127     EXPECT_EQ(0700, stat_mode("com.example/normal"));
    128     EXPECT_EQ(02771, stat_mode("com.example/cache"));
    129     EXPECT_EQ(0700, stat_mode("com.example/cache/file"));
    130 }
    131 
    132 TEST_F(ServiceTest, FixupAppData_Moved) {
    133     LOG(INFO) << "FixupAppData_Moved";
    134 
    135     mkdir("com.example", 10000, 10000, 0700);
    136     mkdir("com.example/foo", 10000, 10000, 0700);
    137     touch("com.example/foo/file", 10000, 20000, 0700);
    138     mkdir("com.example/bar", 10000, 20000, 0700);
    139     touch("com.example/bar/file", 10000, 20000, 0700);
    140 
    141     service->fixupAppData(testUuid, 0);
    142 
    143     EXPECT_EQ(10000, stat_gid("com.example/foo"));
    144     EXPECT_EQ(20000, stat_gid("com.example/foo/file"));
    145     EXPECT_EQ(10000, stat_gid("com.example/bar"));
    146     EXPECT_EQ(10000, stat_gid("com.example/bar/file"));
    147 
    148     service->fixupAppData(testUuid, FLAG_FORCE);
    149 
    150     EXPECT_EQ(10000, stat_gid("com.example/foo"));
    151     EXPECT_EQ(10000, stat_gid("com.example/foo/file"));
    152     EXPECT_EQ(10000, stat_gid("com.example/bar"));
    153     EXPECT_EQ(10000, stat_gid("com.example/bar/file"));
    154 }
    155 
    156 TEST_F(ServiceTest, RmDexNoDalvikCache) {
    157     LOG(INFO) << "RmDexNoDalvikCache";
    158 
    159     // Try to remove a non existing dalvik cache dex. The call should be
    160     // successful because there's nothing to remove.
    161     EXPECT_TRUE(service->rmdex("com.example", "arm").isOk());
    162 }
    163 
    164 }  // namespace installd
    165 }  // namespace android
    166