blob: 6f44e8a75dada76a4cb2980b25f704145f929d16 [file] [log] [blame]
// Copyright 2018 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <gtest/gtest.h>
extern "C" {
#include "./cache.h"
}
#define TESTCACHEFILE "/tmp/testcache"
#define TESTLOCKNAME "/testcachelock"
class CacheTest : public ::testing::Test {
protected:
struct cache cache;
void SetUp() override {
memset(&cache, 0, sizeof(struct cache));
remove(TESTCACHEFILE);
ASSERT_EQ(CACHE_OP_SUCCESS, cache_map(&cache, TESTCACHEFILE,
TESTLOCKNAME, 0x1000));
}
void TearDown() override {
ASSERT_EQ(CACHE_OP_SUCCESS, cache_unmap(&cache));
remove(TESTCACHEFILE);
}
};
TEST_F(CacheTest, InsertFromTwoProcesses) {
const int child_insertions_cnt = 15;
const int parent_insertions_cnt = 10;
if (fork() == 0) {
struct cache cache2 = {0};
cache_map(&cache2, TESTCACHEFILE, TESTLOCKNAME, 0x1000);
for (int i = 0; i < child_insertions_cnt; i++)
EXPECT_EQ(CACHE_INSERTION_SUCCESS, cache_insert(
&cache2, "AAAAA"));
cache_unmap(&cache2);
exit(0);
} else {
for (int i = 0; i < parent_insertions_cnt; i++)
EXPECT_EQ(CACHE_INSERTION_SUCCESS, cache_insert(
&cache, "BBBBBB"));
}
wait(NULL);
EXPECT_EQ(child_insertions_cnt+parent_insertions_cnt, cache.hdr->count);
}
TEST_F(CacheTest, CacheContainsFails) {
EXPECT_EQ(CACHE_CONTAINS_FAILED, cache_contains(&cache, "AAAAAAA"));
}
TEST_F(CacheTest, CacheContainsSucceeds) {
EXPECT_EQ(CACHE_INSERTION_SUCCESS, cache_insert(&cache, "AAAAAAA"));
EXPECT_EQ(CACHE_CONTAINS_SUCCESS, cache_contains(&cache, "AAAAAAA"));
}
TEST_F(CacheTest, CacheContainsAcrossProcess) {
if (fork() == 0) {
struct cache cache2 = {0};
cache_map(&cache2, TESTCACHEFILE, TESTLOCKNAME, 0x1000);
EXPECT_EQ(CACHE_INSERTION_SUCCESS, cache_insert(&cache2, "AAAAAAA"));
cache_unmap(&cache2);
exit(0);
}
wait(NULL);
EXPECT_EQ(CACHE_CONTAINS_SUCCESS, cache_contains(&cache, "AAAAAAA"));
}
TEST_F(CacheTest, CacheInsertIfNotContains) {
cache_insert(&cache, "AAAAAAA");
EXPECT_EQ(CACHE_CONTAINS_SUCCESS, cache_notcontains_insert(
&cache, "AAAAAAA"));
EXPECT_EQ(CACHE_INSERTION_SUCCESS, cache_notcontains_insert(
&cache, "BBBBBBB"));
}
TEST_F(CacheTest, InsertZeroLengthFails) {
EXPECT_EQ(CACHE_INSERTION_FAILED, cache_insert(&cache, ""));
}
TEST_F(CacheTest, CacheHeaderSize) {
EXPECT_EQ(sizeof(struct cachehdr), 16);
}
TEST_F(CacheTest, InsertFailsLengthExceeded) {
int insert_count = (0x1000 - sizeof(struct cachehdr)) / 4;
for (int i = 0; i < insert_count; i++)
cache_insert(&cache, "AAA");
EXPECT_EQ(CACHE_INSERTION_FAILED, cache_insert(&cache, "A"));
}
TEST_F(CacheTest, InsertFailsLengthExceededAcrossProcesses) {
int insert_count = (0x1000 - sizeof(struct cachehdr)) / 4;
if (fork() == 0) {
struct cache cache2 = {0};
cache_map(&cache2, TESTCACHEFILE, TESTLOCKNAME, 0x1000);
for (int i = 0; i < insert_count/2; i++)
cache_insert(&cache2, "AAA");
cache_unmap(&cache2);
exit(0);
}
for (int i = 0; i < insert_count/2; i++)
EXPECT_EQ(CACHE_INSERTION_SUCCESS, cache_insert(&cache, "AAA"));
wait(NULL);
EXPECT_EQ(CACHE_INSERTION_FAILED, cache_insert(&cache, "A"));
}
TEST_F(CacheTest, MapInvalidCache) {
EXPECT_EQ(CACHE_EINVAL, cache_map(NULL, TESTCACHEFILE,
TESTCACHEFILE, 0x1000));
}
TEST_F(CacheTest, MapInvalidCacheFile) {
struct cache cache2 = {0};
EXPECT_EQ(CACHE_EINVAL, cache_map(&cache2, NULL, TESTCACHEFILE, 0x1000));
}
TEST_F(CacheTest, MapInvalidCacheLock) {
struct cache cache2 = {0};
EXPECT_EQ(CACHE_EINVAL, cache_map(&cache2, TESTCACHEFILE, NULL, 0x1000));
}
TEST_F(CacheTest, MapInvalidCacheSize) {
struct cache cache2 = {0};
EXPECT_EQ(CACHE_EINVAL, cache_map(&cache2, TESTCACHEFILE,
TESTCACHEFILE, 0));
}
TEST_F(CacheTest, UnmapInvalidCache) {
EXPECT_EQ(CACHE_EINVAL, cache_unmap(NULL));
}
TEST_F(CacheTest, InsertInvalidCache) {
EXPECT_EQ(CACHE_EINVAL, cache_insert(NULL, "AAA"));
}
TEST_F(CacheTest, InsertNull) {
EXPECT_EQ(CACHE_EINVAL, cache_insert(&cache, NULL));
}
TEST_F(CacheTest, ContainsInvalidCache) {
EXPECT_EQ(CACHE_EINVAL, cache_contains(NULL, "AAA"));
}
TEST_F(CacheTest, ContainsInvalidNull) {
EXPECT_EQ(CACHE_EINVAL, cache_contains(&cache, NULL));
}
GTEST_API_ int main(int argc, char *argv[]) {
int ret;
remove(TESTCACHEFILE);
::testing::InitGoogleTest(&argc, argv);
ret = RUN_ALL_TESTS();
if (ret == 0)
printf("[+] Cache tests succeeded\n");
else
printf("[x] Cache tests failed\n");
return ret;
}