blob: e99519d9f0d944eeb420e2698c9bbbb4edf5a8e5 [file] [log] [blame]
/*
* Copyright (c) 2010 The Native Client 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 <errno.h>
#include <sys/mman.h>
#include <cstdlib>
#include <cstring>
#include "gtest/gtest.h"
namespace {
class MemTests : public ::testing::Test {
protected:
// Use 64Kb regions in the memory tests. This is usually a whole number of
// pages. The 32Kb size is used for certain other failure modes.
const size_t k64Kbytes = 64 * 1024;
const size_t k32Kbytes = 32 * 1024;
// |MAP_ANONYMOUS| expects a filedesc of -1. While this is not strictly true
// on all systems, portable code should work this way.
const int kAnonymousFiledesc = -1;
// When |MAP_ANONYMOUS| is not specified, any negative file desc should report
// EBADF.
const int kBadFiledesc = -3;
MemTests() {
// You can do set-up work for each test here.
}
~MemTests() override {}
void SetUp() override {}
void TearDown() override {}
};
} // namespace
// Try to mmap a 0-length region. This is expected to fail.
TEST_F(MemTests, DISABLED_TestZeroLengthRegion) {
void* mmap_ptr = mmap(NULL, 0, PROT_READ, MAP_PRIVATE | MAP_ANONYMOUS,
kAnonymousFiledesc, 0);
EXPECT_EQ(MAP_FAILED, mmap_ptr);
EXPECT_EQ(EINVAL, errno);
}
// Hand in a bad file descriptor, this test is successful if mmap() fails.
// The |MAP_ANONYMOUS| flag is deliberately not used for this test, because
// we are trying to map an actual (but bad) filedesc.
TEST_F(MemTests, DISABLED_TestBadFiledesc) {
void* mmap_ptr =
mmap(NULL, k64Kbytes, PROT_READ, MAP_PRIVATE, kBadFiledesc, 0);
EXPECT_EQ(MAP_FAILED, mmap_ptr);
EXPECT_EQ(EBADF, errno);
}
// Verify that mmap does not fail if a bad hint address is passed, but
// |MMAP_FIXED| is not specified.
TEST_F(MemTests, DISABLED_TestMmapBadHint) {
void* bad_hint = (void*)0x123;
void* mmap_ptr = mmap(bad_hint, k64Kbytes, PROT_READ,
MAP_PRIVATE | MAP_ANONYMOUS, kAnonymousFiledesc, 0);
EXPECT_NE(MAP_FAILED, mmap_ptr);
EXPECT_NE(mmap_ptr, bad_hint);
EXPECT_EQ(munmap(mmap_ptr, k64Kbytes), 0);
}
// Verify that mmap does fail if a bad hint address is passed and
// |MMAP_FIXED| is specified.
TEST_F(MemTests, DISABLED_TestMmapBadHintFixed) {
void* bad_hint = (void*)0x123;
void* mmap_ptr =
mmap(bad_hint, k64Kbytes, PROT_READ,
MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, kAnonymousFiledesc, 0);
EXPECT_EQ(MAP_FAILED, mmap_ptr);
}
// Test mmap() and munmap(), since these often to go together. Tries to mmap
// a 64 Kb region of memory and then tests to make sure that the pages have all
// been 0-filled.
TEST_F(MemTests, DISABLED_TestMmapMunmap) {
void* mmap_ptr = mmap(NULL, k64Kbytes, PROT_READ, MAP_PRIVATE | MAP_ANONYMOUS,
kAnonymousFiledesc, 0);
EXPECT_NE(MAP_FAILED, mmap_ptr);
// Create a zero-filled region on the heap for comparison with the mmaped
// region.
void* zeroes = std::malloc(k64Kbytes);
std::memset(zeroes, 0, k64Kbytes);
EXPECT_EQ(std::memcmp(mmap_ptr, zeroes, k64Kbytes), 0);
// Attempt to release the mapped memory.
EXPECT_EQ(munmap(mmap_ptr, k64Kbytes), 0);
std::free(zeroes);
}
// Verify that mmap into the NULL pointer guard page will fail. This uses the
// |MAP_FIXED| flag to try an force mmap() to pin the region at NULL.
TEST_F(MemTests, DISABLED_TestMmapNULL) {
void* mmap_ptr =
mmap(NULL, k64Kbytes, PROT_READ, MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED,
kAnonymousFiledesc, 0);
EXPECT_EQ(MAP_FAILED, mmap_ptr);
EXPECT_EQ(EINVAL, errno);
}
// Attempt to allocate 32Kb, starting at 32Kb. This should fail.
TEST_F(MemTests, DISABLED_TestMmap32k) {
void* mmap_ptr =
mmap(reinterpret_cast<void*>(k32Kbytes), k32Kbytes, PROT_READ,
MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, kAnonymousFiledesc, 0);
EXPECT_EQ(MAP_FAILED, mmap_ptr);
EXPECT_EQ(EINVAL, errno);
}
// Verify that mmap() with the |MAP_FIXED| flag and a non-page-aligned address
// will fail.
TEST_F(MemTests, DISABLED_TestMmapNonPageAligned) {
// Reserve some legal (page-aligned) address space in which to perform the
// test.
char* local_heap = reinterpret_cast<char*>(mmap(NULL, k64Kbytes, PROT_NONE,
MAP_PRIVATE | MAP_ANONYMOUS,
kAnonymousFiledesc, 0));
EXPECT_NE(MAP_FAILED, local_heap);
void* unaligned_ptr =
mmap(static_cast<void*>(local_heap + 0x100), k64Kbytes, PROT_READ,
MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, kAnonymousFiledesc, 0);
EXPECT_EQ(MAP_FAILED, unaligned_ptr);
EXPECT_EQ(EINVAL, errno);
}