f99ad113b9
Change-Id: I8228c9a796e68e920c6a7dfc154c4b70ba66b082
439 lines
14 KiB
C++
439 lines
14 KiB
C++
/*
|
|
* Copyright (C) 2010 The Android Open Source Project
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
#define LOG_TAG "ObbFile_test"
|
|
#include <androidfw/BackupHelpers.h>
|
|
#include <utils/Log.h>
|
|
#include <utils/String8.h>
|
|
|
|
#include <gtest/gtest.h>
|
|
|
|
#include <sys/types.h>
|
|
#include <sys/stat.h>
|
|
#include <fcntl.h>
|
|
#include <string.h>
|
|
|
|
namespace android {
|
|
|
|
#define TEST_FILENAME "/test.bd"
|
|
|
|
// keys of different lengths to test padding
|
|
#define KEY1 "key1"
|
|
#define KEY2 "key2a"
|
|
#define KEY3 "key3bc"
|
|
#define KEY4 "key4def"
|
|
|
|
// payloads of different lengths to test padding
|
|
#define DATA1 "abcdefg"
|
|
#define DATA2 "hijklmnopq"
|
|
#define DATA3 "rstuvwxyz"
|
|
// KEY4 is only ever deleted
|
|
|
|
class BackupDataTest : public testing::Test {
|
|
protected:
|
|
char* m_external_storage;
|
|
char* m_filename;
|
|
String8 mKey1;
|
|
String8 mKey2;
|
|
String8 mKey3;
|
|
String8 mKey4;
|
|
|
|
virtual void SetUp() {
|
|
m_external_storage = getenv("EXTERNAL_STORAGE");
|
|
|
|
const int totalLen = strlen(m_external_storage) + strlen(TEST_FILENAME) + 1;
|
|
m_filename = new char[totalLen];
|
|
snprintf(m_filename, totalLen, "%s%s", m_external_storage, TEST_FILENAME);
|
|
|
|
::unlink(m_filename);
|
|
int fd = ::open(m_filename, O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
|
|
if (fd < 0) {
|
|
FAIL() << "Couldn't create " << m_filename << " for writing";
|
|
}
|
|
mKey1 = String8(KEY1);
|
|
mKey2 = String8(KEY2);
|
|
mKey3 = String8(KEY3);
|
|
mKey4 = String8(KEY4);
|
|
}
|
|
|
|
virtual void TearDown() {
|
|
}
|
|
};
|
|
|
|
TEST_F(BackupDataTest, WriteAndReadSingle) {
|
|
int fd = ::open(m_filename, O_WRONLY);
|
|
BackupDataWriter* writer = new BackupDataWriter(fd);
|
|
|
|
EXPECT_EQ(NO_ERROR, writer->WriteEntityHeader(mKey1, sizeof(DATA1)))
|
|
<< "WriteEntityHeader returned an error";
|
|
EXPECT_EQ(NO_ERROR, writer->WriteEntityData(DATA1, sizeof(DATA1)))
|
|
<< "WriteEntityData returned an error";
|
|
|
|
::close(fd);
|
|
fd = ::open(m_filename, O_RDONLY);
|
|
BackupDataReader* reader = new BackupDataReader(fd);
|
|
EXPECT_EQ(NO_ERROR, reader->Status())
|
|
<< "Reader ctor failed";
|
|
|
|
bool done;
|
|
int type;
|
|
reader->ReadNextHeader(&done, &type);
|
|
EXPECT_EQ(BACKUP_HEADER_ENTITY_V1, type)
|
|
<< "wrong type from ReadNextHeader";
|
|
|
|
String8 key;
|
|
size_t dataSize;
|
|
EXPECT_EQ(NO_ERROR, reader->ReadEntityHeader(&key, &dataSize))
|
|
<< "ReadEntityHeader returned an error";
|
|
EXPECT_EQ(mKey1, key)
|
|
<< "wrong key from ReadEntityHeader";
|
|
EXPECT_EQ(sizeof(DATA1), dataSize)
|
|
<< "wrong size from ReadEntityHeader";
|
|
|
|
char* dataBytes = new char[dataSize];
|
|
EXPECT_EQ((int) dataSize, reader->ReadEntityData(dataBytes, dataSize))
|
|
<< "ReadEntityData returned an error";
|
|
for (unsigned int i = 0; i < sizeof(DATA1); i++) {
|
|
EXPECT_EQ(DATA1[i], dataBytes[i])
|
|
<< "data character " << i << " should be equal";
|
|
}
|
|
delete dataBytes;
|
|
delete writer;
|
|
delete reader;
|
|
}
|
|
|
|
TEST_F(BackupDataTest, WriteAndReadMultiple) {
|
|
int fd = ::open(m_filename, O_WRONLY);
|
|
BackupDataWriter* writer = new BackupDataWriter(fd);
|
|
writer->WriteEntityHeader(mKey1, sizeof(DATA1));
|
|
writer->WriteEntityData(DATA1, sizeof(DATA1));
|
|
writer->WriteEntityHeader(mKey2, sizeof(DATA2));
|
|
writer->WriteEntityData(DATA2, sizeof(DATA2));
|
|
|
|
::close(fd);
|
|
fd = ::open(m_filename, O_RDONLY);
|
|
BackupDataReader* reader = new BackupDataReader(fd);
|
|
|
|
bool done;
|
|
int type;
|
|
String8 key;
|
|
size_t dataSize;
|
|
char* dataBytes;
|
|
// read first entity
|
|
reader->ReadNextHeader(&done, &type);
|
|
reader->ReadEntityHeader(&key, &dataSize);
|
|
dataBytes = new char[dataSize];
|
|
reader->ReadEntityData(dataBytes, dataSize);
|
|
delete dataBytes;
|
|
|
|
// read and verify second entity
|
|
reader->ReadNextHeader(&done, &type);
|
|
EXPECT_EQ(BACKUP_HEADER_ENTITY_V1, type)
|
|
<< "wrong type from ReadNextHeader";
|
|
|
|
EXPECT_EQ(NO_ERROR, reader->ReadEntityHeader(&key, &dataSize))
|
|
<< "ReadEntityHeader returned an error on second entity";
|
|
EXPECT_EQ(mKey2, key)
|
|
<< "wrong key from ReadEntityHeader on second entity";
|
|
EXPECT_EQ(sizeof(DATA2), dataSize)
|
|
<< "wrong size from ReadEntityHeader on second entity";
|
|
|
|
dataBytes = new char[dataSize];
|
|
EXPECT_EQ((int)dataSize, reader->ReadEntityData(dataBytes, dataSize))
|
|
<< "ReadEntityData returned an error on second entity";
|
|
for (unsigned int i = 0; i < sizeof(DATA2); i++) {
|
|
EXPECT_EQ(DATA2[i], dataBytes[i])
|
|
<< "data character " << i << " should be equal";
|
|
}
|
|
delete dataBytes;
|
|
delete writer;
|
|
delete reader;
|
|
}
|
|
|
|
TEST_F(BackupDataTest, SkipEntity) {
|
|
int fd = ::open(m_filename, O_WRONLY);
|
|
BackupDataWriter* writer = new BackupDataWriter(fd);
|
|
writer->WriteEntityHeader(mKey1, sizeof(DATA1));
|
|
writer->WriteEntityData(DATA1, sizeof(DATA1));
|
|
writer->WriteEntityHeader(mKey2, sizeof(DATA2));
|
|
writer->WriteEntityData(DATA2, sizeof(DATA2));
|
|
writer->WriteEntityHeader(mKey3, sizeof(DATA3));
|
|
writer->WriteEntityData(DATA3, sizeof(DATA3));
|
|
|
|
::close(fd);
|
|
fd = ::open(m_filename, O_RDONLY);
|
|
BackupDataReader* reader = new BackupDataReader(fd);
|
|
|
|
bool done;
|
|
int type;
|
|
String8 key;
|
|
size_t dataSize;
|
|
char* dataBytes;
|
|
// read first entity
|
|
reader->ReadNextHeader(&done, &type);
|
|
reader->ReadEntityHeader(&key, &dataSize);
|
|
dataBytes = new char[dataSize];
|
|
reader->ReadEntityData(dataBytes, dataSize);
|
|
delete dataBytes;
|
|
|
|
// skip second entity
|
|
reader->ReadNextHeader(&done, &type);
|
|
reader->ReadEntityHeader(&key, &dataSize);
|
|
reader->SkipEntityData();
|
|
|
|
// read and verify third entity
|
|
reader->ReadNextHeader(&done, &type);
|
|
EXPECT_EQ(BACKUP_HEADER_ENTITY_V1, type)
|
|
<< "wrong type from ReadNextHeader after skip";
|
|
|
|
EXPECT_EQ(NO_ERROR, reader->ReadEntityHeader(&key, &dataSize))
|
|
<< "ReadEntityHeader returned an error on third entity";
|
|
EXPECT_EQ(mKey3, key)
|
|
<< "wrong key from ReadEntityHeader on third entity";
|
|
EXPECT_EQ(sizeof(DATA3), dataSize)
|
|
<< "wrong size from ReadEntityHeader on third entity";
|
|
|
|
dataBytes = new char[dataSize];
|
|
EXPECT_EQ((int) dataSize, reader->ReadEntityData(dataBytes, dataSize))
|
|
<< "ReadEntityData returned an error on third entity";
|
|
for (unsigned int i = 0; i < sizeof(DATA3); i++) {
|
|
EXPECT_EQ(DATA3[i], dataBytes[i])
|
|
<< "data character " << i << " should be equal";
|
|
}
|
|
delete dataBytes;
|
|
delete writer;
|
|
delete reader;
|
|
}
|
|
|
|
TEST_F(BackupDataTest, DeleteEntity) {
|
|
int fd = ::open(m_filename, O_WRONLY);
|
|
BackupDataWriter* writer = new BackupDataWriter(fd);
|
|
writer->WriteEntityHeader(mKey1, sizeof(DATA1));
|
|
writer->WriteEntityData(DATA1, sizeof(DATA1));
|
|
writer->WriteEntityHeader(mKey2, -1);
|
|
|
|
::close(fd);
|
|
fd = ::open(m_filename, O_RDONLY);
|
|
BackupDataReader* reader = new BackupDataReader(fd);
|
|
|
|
bool done;
|
|
int type;
|
|
String8 key;
|
|
size_t dataSize;
|
|
char* dataBytes;
|
|
// read first entity
|
|
reader->ReadNextHeader(&done, &type);
|
|
reader->ReadEntityHeader(&key, &dataSize);
|
|
dataBytes = new char[dataSize];
|
|
reader->ReadEntityData(dataBytes, dataSize);
|
|
delete dataBytes;
|
|
|
|
// read and verify deletion
|
|
reader->ReadNextHeader(&done, &type);
|
|
EXPECT_EQ(BACKUP_HEADER_ENTITY_V1, type)
|
|
<< "wrong type from ReadNextHeader on deletion";
|
|
|
|
EXPECT_EQ(NO_ERROR, reader->ReadEntityHeader(&key, &dataSize))
|
|
<< "ReadEntityHeader returned an error on second entity";
|
|
EXPECT_EQ(mKey2, key)
|
|
<< "wrong key from ReadEntityHeader on second entity";
|
|
EXPECT_EQ(-1, (int) dataSize)
|
|
<< "not recognizing deletion on second entity";
|
|
|
|
delete writer;
|
|
delete reader;
|
|
}
|
|
|
|
TEST_F(BackupDataTest, EneityAfterDelete) {
|
|
int fd = ::open(m_filename, O_WRONLY);
|
|
BackupDataWriter* writer = new BackupDataWriter(fd);
|
|
writer->WriteEntityHeader(mKey1, sizeof(DATA1));
|
|
writer->WriteEntityData(DATA1, sizeof(DATA1));
|
|
writer->WriteEntityHeader(mKey2, -1);
|
|
writer->WriteEntityHeader(mKey3, sizeof(DATA3));
|
|
writer->WriteEntityData(DATA3, sizeof(DATA3));
|
|
|
|
::close(fd);
|
|
fd = ::open(m_filename, O_RDONLY);
|
|
BackupDataReader* reader = new BackupDataReader(fd);
|
|
|
|
bool done;
|
|
int type;
|
|
String8 key;
|
|
size_t dataSize;
|
|
char* dataBytes;
|
|
// read first entity
|
|
reader->ReadNextHeader(&done, &type);
|
|
reader->ReadEntityHeader(&key, &dataSize);
|
|
dataBytes = new char[dataSize];
|
|
reader->ReadEntityData(dataBytes, dataSize);
|
|
delete dataBytes;
|
|
|
|
// read and verify deletion
|
|
reader->ReadNextHeader(&done, &type);
|
|
EXPECT_EQ(BACKUP_HEADER_ENTITY_V1, type)
|
|
<< "wrong type from ReadNextHeader on deletion";
|
|
|
|
EXPECT_EQ(NO_ERROR, reader->ReadEntityHeader(&key, &dataSize))
|
|
<< "ReadEntityHeader returned an error on second entity";
|
|
EXPECT_EQ(mKey2, key)
|
|
<< "wrong key from ReadEntityHeader on second entity";
|
|
EXPECT_EQ(-1, (int)dataSize)
|
|
<< "not recognizing deletion on second entity";
|
|
|
|
// read and verify third entity
|
|
reader->ReadNextHeader(&done, &type);
|
|
EXPECT_EQ(BACKUP_HEADER_ENTITY_V1, type)
|
|
<< "wrong type from ReadNextHeader after deletion";
|
|
|
|
EXPECT_EQ(NO_ERROR, reader->ReadEntityHeader(&key, &dataSize))
|
|
<< "ReadEntityHeader returned an error on third entity";
|
|
EXPECT_EQ(mKey3, key)
|
|
<< "wrong key from ReadEntityHeader on third entity";
|
|
EXPECT_EQ(sizeof(DATA3), dataSize)
|
|
<< "wrong size from ReadEntityHeader on third entity";
|
|
|
|
dataBytes = new char[dataSize];
|
|
EXPECT_EQ((int) dataSize, reader->ReadEntityData(dataBytes, dataSize))
|
|
<< "ReadEntityData returned an error on third entity";
|
|
for (unsigned int i = 0; i < sizeof(DATA3); i++) {
|
|
EXPECT_EQ(DATA3[i], dataBytes[i])
|
|
<< "data character " << i << " should be equal";
|
|
}
|
|
delete dataBytes;
|
|
delete writer;
|
|
delete reader;
|
|
}
|
|
|
|
TEST_F(BackupDataTest, OnlyDeleteEntities) {
|
|
int fd = ::open(m_filename, O_WRONLY);
|
|
BackupDataWriter* writer = new BackupDataWriter(fd);
|
|
writer->WriteEntityHeader(mKey1, -1);
|
|
writer->WriteEntityHeader(mKey2, -1);
|
|
writer->WriteEntityHeader(mKey3, -1);
|
|
writer->WriteEntityHeader(mKey4, -1);
|
|
|
|
::close(fd);
|
|
fd = ::open(m_filename, O_RDONLY);
|
|
BackupDataReader* reader = new BackupDataReader(fd);
|
|
|
|
bool done;
|
|
int type;
|
|
String8 key;
|
|
size_t dataSize;
|
|
// read and verify first deletion
|
|
reader->ReadNextHeader(&done, &type);
|
|
EXPECT_EQ(BACKUP_HEADER_ENTITY_V1, type)
|
|
<< "wrong type from ReadNextHeader first deletion";
|
|
|
|
EXPECT_EQ(NO_ERROR, reader->ReadEntityHeader(&key, &dataSize))
|
|
<< "ReadEntityHeader returned an error on first entity";
|
|
EXPECT_EQ(mKey1, key)
|
|
<< "wrong key from ReadEntityHeader on first entity";
|
|
EXPECT_EQ(-1, (int) dataSize)
|
|
<< "not recognizing deletion on first entity";
|
|
|
|
// read and verify second deletion
|
|
reader->ReadNextHeader(&done, &type);
|
|
EXPECT_EQ(BACKUP_HEADER_ENTITY_V1, type)
|
|
<< "wrong type from ReadNextHeader second deletion";
|
|
|
|
EXPECT_EQ(NO_ERROR, reader->ReadEntityHeader(&key, &dataSize))
|
|
<< "ReadEntityHeader returned an error on second entity";
|
|
EXPECT_EQ(mKey2, key)
|
|
<< "wrong key from ReadEntityHeader on second entity";
|
|
EXPECT_EQ(-1, (int) dataSize)
|
|
<< "not recognizing deletion on second entity";
|
|
|
|
// read and verify third deletion
|
|
reader->ReadNextHeader(&done, &type);
|
|
EXPECT_EQ(BACKUP_HEADER_ENTITY_V1, type)
|
|
<< "wrong type from ReadNextHeader third deletion";
|
|
|
|
EXPECT_EQ(NO_ERROR, reader->ReadEntityHeader(&key, &dataSize))
|
|
<< "ReadEntityHeader returned an error on third entity";
|
|
EXPECT_EQ(mKey3, key)
|
|
<< "wrong key from ReadEntityHeader on third entity";
|
|
EXPECT_EQ(-1, (int) dataSize)
|
|
<< "not recognizing deletion on third entity";
|
|
|
|
// read and verify fourth deletion
|
|
reader->ReadNextHeader(&done, &type);
|
|
EXPECT_EQ(BACKUP_HEADER_ENTITY_V1, type)
|
|
<< "wrong type from ReadNextHeader fourth deletion";
|
|
|
|
EXPECT_EQ(NO_ERROR, reader->ReadEntityHeader(&key, &dataSize))
|
|
<< "ReadEntityHeader returned an error on fourth entity";
|
|
EXPECT_EQ(mKey4, key)
|
|
<< "wrong key from ReadEntityHeader on fourth entity";
|
|
EXPECT_EQ(-1, (int) dataSize)
|
|
<< "not recognizing deletion on fourth entity";
|
|
|
|
delete writer;
|
|
delete reader;
|
|
}
|
|
|
|
TEST_F(BackupDataTest, ReadDeletedEntityData) {
|
|
int fd = ::open(m_filename, O_WRONLY);
|
|
BackupDataWriter* writer = new BackupDataWriter(fd);
|
|
writer->WriteEntityHeader(mKey1, -1);
|
|
writer->WriteEntityHeader(mKey2, -1);
|
|
|
|
::close(fd);
|
|
fd = ::open(m_filename, O_RDONLY);
|
|
BackupDataReader* reader = new BackupDataReader(fd);
|
|
|
|
bool done;
|
|
int type;
|
|
String8 key;
|
|
size_t dataSize;
|
|
// read and verify first deletion
|
|
reader->ReadNextHeader(&done, &type);
|
|
EXPECT_EQ(BACKUP_HEADER_ENTITY_V1, type)
|
|
<< "wrong type from ReadNextHeader first deletion";
|
|
|
|
EXPECT_EQ(NO_ERROR, reader->ReadEntityHeader(&key, &dataSize))
|
|
<< "ReadEntityHeader returned an error on first entity";
|
|
EXPECT_EQ(mKey1, key)
|
|
<< "wrong key from ReadEntityHeader on first entity";
|
|
EXPECT_EQ(-1, (int) dataSize)
|
|
<< "not recognizing deletion on first entity";
|
|
|
|
// erroneously try to read first entity data
|
|
char* dataBytes = new char[10];
|
|
dataBytes[0] = 'A';
|
|
EXPECT_EQ(NO_ERROR, reader->ReadEntityData(dataBytes, dataSize));
|
|
// expect dataBytes to be unmodofied
|
|
EXPECT_EQ('A', dataBytes[0]);
|
|
|
|
// read and verify second deletion
|
|
reader->ReadNextHeader(&done, &type);
|
|
EXPECT_EQ(BACKUP_HEADER_ENTITY_V1, type)
|
|
<< "wrong type from ReadNextHeader second deletion";
|
|
|
|
EXPECT_EQ(NO_ERROR, reader->ReadEntityHeader(&key, &dataSize))
|
|
<< "ReadEntityHeader returned an error on second entity";
|
|
EXPECT_EQ(mKey2, key)
|
|
<< "wrong key from ReadEntityHeader on second entity";
|
|
EXPECT_EQ(-1, (int) dataSize)
|
|
<< "not recognizing deletion on second entity";
|
|
|
|
delete writer;
|
|
delete reader;
|
|
}
|
|
|
|
}
|