1// Copyright 2014 The Android Open Source Project
2//
3// This software is licensed under the terms of the GNU General Public
4// License version 2, as published by the Free Software Foundation, and
5// may be copied, distributed, and modified under those terms.
6//
7// This program is distributed in the hope that it will be useful,
8// but WITHOUT ANY WARRANTY; without even the implied warranty of
9// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10// GNU General Public License for more details.
11
12#include "android/filesystems/ext4_utils.h"
13
14#include "android/base/EintrWrapper.h"
15#include "android/base/Log.h"
16#include "android/base/files/ScopedStdioFile.h"
17#include "android/filesystems/testing/TestExt4ImageHeader.h"
18#include "android/filesystems/testing/TestSupport.h"
19
20#include <gtest/gtest.h>
21
22#include <string>
23
24#include <stdio.h>
25#include <stdlib.h>
26#include <string.h>
27
28#ifdef _WIN32
29#include <windows.h>
30#endif
31
32using android::base::ScopedStdioFile;
33using android::testing::CreateTempFilePath;
34
35class Ext4UtilsTest : public ::testing::Test {
36public:
37    Ext4UtilsTest() : mTempFilePath() {
38        ::memset(mImage, 0, sizeof mImage);
39        ::memcpy(mImage, kTestExt4ImageHeader, kTestExt4ImageHeaderSize);
40    }
41
42    ~Ext4UtilsTest() {
43        if (!mTempFilePath.empty()) {
44            HANDLE_EINTR(unlink(mTempFilePath.c_str()));
45        }
46    }
47
48protected:
49    // Create a temporary file with up to |maxBytes| bytes of |mImage|
50    // in it, and return its path. The file will be removed in the
51    // destructor.
52    const char* createTempFile(size_t maxBytes) {
53        CHECK(maxBytes <= sizeof mImage);
54        // TODO(digit): Replace with something else.
55        mTempFilePath = CreateTempFilePath();
56        ScopedStdioFile file(fopen(mTempFilePath.c_str(), "wb"));
57        PCHECK(file.get()) << "Could not create temporary file!";
58        PCHECK(::fwrite(mImage, maxBytes, 1, file.get()) == 1)
59                << "Could not write " << maxBytes << " bytes to "
60                << "temporary file";
61        file.close();
62        return mTempFilePath.c_str();
63    }
64
65    // Create the path of a temporary file, but do not create or
66    // populate it. The file is removed in the destructor.
67    const char* createTempPath() {
68        mTempFilePath = CreateTempFilePath();
69        return mTempFilePath.c_str();
70    }
71
72    std::string mTempFilePath;
73    char mImage[kTestExt4ImageHeaderSize * 2U];
74};
75
76TEST_F(Ext4UtilsTest, android_pathIsExt4PartitionImage) {
77    const char* path = createTempFile(kTestExt4ImageHeaderSize);
78    EXPECT_TRUE(android_pathIsExt4PartitionImage(path));
79}
80
81TEST_F(Ext4UtilsTest, android_pathIsExt4PartitionImageTruncated) {
82    const char* path = createTempFile(kTestExt4ImageHeaderSize - 2U);
83    EXPECT_FALSE(android_pathIsExt4PartitionImage(path));
84}
85
86TEST_F(Ext4UtilsTest, android_pathIsExt4PartitionImageCorrupted) {
87    memset(mImage, 0x55, sizeof mImage);
88    const char* path = createTempFile(sizeof mImage);
89    EXPECT_FALSE(android_pathIsExt4PartitionImage(path));
90}
91
92TEST_F(Ext4UtilsTest, android_pathIsExt4PartitionImageBadMagic1) {
93    mImage[kTestExt4ImageHeaderSize - 1] = 0;
94    const char* path = createTempFile(sizeof mImage);
95    EXPECT_FALSE(android_pathIsExt4PartitionImage(path));
96}
97
98TEST_F(Ext4UtilsTest, android_pathIsExt4PartitionImageBadMagic2) {
99    mImage[kTestExt4ImageHeaderSize - 2] = 0;
100    const char* path = createTempFile(sizeof mImage);
101    EXPECT_FALSE(android_pathIsExt4PartitionImage(path));
102}
103
104TEST_F(Ext4UtilsTest, android_createEmptyExt4Partition) {
105    const char* tempPath = createTempPath();
106    uint64_t kSize = 32 * 1024 * 1024;
107    int ret = android_createEmptyExt4Image(tempPath, kSize, "cache");
108    EXPECT_EQ(0, ret);
109    EXPECT_TRUE(android_pathIsExt4PartitionImage(tempPath));
110}
111