upload android base code part6

This commit is contained in:
August 2018-08-08 17:48:24 +08:00
parent 421e214c7d
commit 4e516ec6ed
35396 changed files with 9188716 additions and 0 deletions

View file

@ -0,0 +1,89 @@
// Copyright (C) 2014 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.
cc_defaults {
name: "libcutils_test_default",
srcs: ["sockets_test.cpp"],
target: {
android: {
srcs: [
"AshmemTest.cpp",
"MemsetTest.cpp",
"PropertiesTest.cpp",
"sched_policy_test.cpp",
"trace-dev_test.cpp",
"test_str_parms.cpp",
"android_get_control_socket_test.cpp",
"android_get_control_file_test.cpp",
"multiuser_test.cpp",
"fs_config.cpp",
],
},
not_windows: {
srcs: [
"test_str_parms.cpp",
],
},
},
multilib: {
lib32: {
suffix: "32",
},
lib64: {
suffix: "64",
},
},
cflags: [
"-Wall",
"-Wextra",
"-Werror",
],
}
test_libraries = [
"libcutils",
"liblog",
"libbase",
]
cc_test {
name: "libcutils_test",
test_suites: ["device-tests"],
defaults: ["libcutils_test_default"],
host_supported: true,
shared_libs: test_libraries,
}
cc_test {
name: "libcutils_test_static",
test_suites: ["device-tests"],
defaults: ["libcutils_test_default"],
static_libs: ["libc"] + test_libraries,
stl: "libc++_static",
target: {
android: {
static_executable: true,
},
windows: {
host_ldlibs: ["-lws2_32"],
enabled: true,
},
},
}

View file

@ -0,0 +1,26 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2017 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.
-->
<configuration description="Config for libcutils_test">
<target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
<option name="cleanup" value="true" />
<option name="push" value="libcutils_test->/data/local/tmp/libcutils_test" />
</target_preparer>
<option name="test-suite-tag" value="apct" />
<test class="com.android.tradefed.testtype.GTest" >
<option name="native-test-device-path" value="/data/local/tmp" />
<option name="module-name" value="libcutils_test" />
</test>
</configuration>

View file

@ -0,0 +1,251 @@
/*
* Copyright (C) 2016 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.
*/
#include <android-base/unique_fd.h>
#include <cutils/ashmem.h>
#include <gtest/gtest.h>
#include <linux/fs.h>
#include <sys/mman.h>
using android::base::unique_fd;
void TestCreateRegion(size_t size, unique_fd &fd, int prot) {
fd = unique_fd(ashmem_create_region(nullptr, size));
ASSERT_TRUE(fd >= 0);
ASSERT_TRUE(ashmem_valid(fd));
ASSERT_EQ(size, static_cast<size_t>(ashmem_get_size_region(fd)));
ASSERT_EQ(0, ashmem_set_prot_region(fd, prot));
}
void TestMmap(const unique_fd& fd, size_t size, int prot, void** region, off_t off = 0) {
*region = mmap(nullptr, size, prot, MAP_SHARED, fd, off);
ASSERT_NE(MAP_FAILED, *region);
}
void TestProtDenied(const unique_fd &fd, size_t size, int prot) {
EXPECT_EQ(MAP_FAILED, mmap(nullptr, size, prot, MAP_SHARED, fd, 0));
}
void TestProtIs(const unique_fd& fd, int prot) {
EXPECT_EQ(prot, ioctl(fd, ASHMEM_GET_PROT_MASK));
}
void FillData(uint8_t* data, size_t dataLen) {
for (size_t i = 0; i < dataLen; i++) {
data[i] = i & 0xFF;
}
}
TEST(AshmemTest, BasicTest) {
constexpr size_t size = PAGE_SIZE;
uint8_t data[size];
FillData(data, size);
unique_fd fd;
ASSERT_NO_FATAL_FAILURE(TestCreateRegion(size, fd, PROT_READ | PROT_WRITE));
void *region1;
ASSERT_NO_FATAL_FAILURE(TestMmap(fd, size, PROT_READ | PROT_WRITE, &region1));
memcpy(region1, &data, size);
ASSERT_EQ(0, memcmp(region1, &data, size));
EXPECT_EQ(0, munmap(region1, size));
void *region2;
ASSERT_NO_FATAL_FAILURE(TestMmap(fd, size, PROT_READ, &region2));
ASSERT_EQ(0, memcmp(region2, &data, size));
EXPECT_EQ(0, munmap(region2, size));
}
TEST(AshmemTest, ForkTest) {
constexpr size_t size = PAGE_SIZE;
uint8_t data[size];
FillData(data, size);
unique_fd fd;
ASSERT_NO_FATAL_FAILURE(TestCreateRegion(size, fd, PROT_READ | PROT_WRITE));
void *region1;
ASSERT_NO_FATAL_FAILURE(TestMmap(fd, size, PROT_READ | PROT_WRITE, &region1));
memcpy(region1, &data, size);
ASSERT_EQ(0, memcmp(region1, &data, size));
EXPECT_EQ(0, munmap(region1, size));
ASSERT_EXIT({
void *region2 = mmap(nullptr, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if (region2 == MAP_FAILED) {
_exit(1);
}
if (memcmp(region2, &data, size) != 0) {
_exit(2);
}
memset(region2, 0, size);
munmap(region2, size);
_exit(0);
}, ::testing::ExitedWithCode(0),"");
memset(&data, 0, size);
void *region2;
ASSERT_NO_FATAL_FAILURE(TestMmap(fd, size, PROT_READ | PROT_WRITE, &region2));
ASSERT_EQ(0, memcmp(region2, &data, size));
EXPECT_EQ(0, munmap(region2, size));
}
TEST(AshmemTest, FileOperationsTest) {
unique_fd fd;
void* region;
// Allocate a 4-page buffer, but leave page-sized holes on either side
constexpr size_t size = PAGE_SIZE * 4;
constexpr size_t dataSize = PAGE_SIZE * 2;
constexpr size_t holeSize = PAGE_SIZE;
ASSERT_NO_FATAL_FAILURE(TestCreateRegion(size, fd, PROT_READ | PROT_WRITE));
ASSERT_NO_FATAL_FAILURE(TestMmap(fd, dataSize, PROT_READ | PROT_WRITE, &region, holeSize));
uint8_t data[dataSize];
FillData(data, dataSize);
memcpy(region, data, dataSize);
constexpr off_t dataStart = holeSize;
constexpr off_t dataEnd = dataStart + dataSize;
// The sequence of seeks below looks something like this:
//
// [ ][data][data][ ]
// --^ lseek(99, SEEK_SET)
// ------^ lseek(dataStart, SEEK_CUR)
// ------^ lseek(0, SEEK_DATA)
// ------------^ lseek(dataStart, SEEK_HOLE)
// ^-- lseek(-99, SEEK_END)
// ^------ lseek(-dataStart, SEEK_CUR)
const struct {
// lseek() parameters
off_t offset;
int whence;
// Expected lseek() return value
off_t ret;
} seeks[] = {
{99, SEEK_SET, 99}, {dataStart, SEEK_CUR, dataStart + 99},
{0, SEEK_DATA, dataStart}, {dataStart, SEEK_HOLE, dataEnd},
{-99, SEEK_END, size - 99}, {-dataStart, SEEK_CUR, dataEnd - 99},
};
for (const auto& cfg : seeks) {
errno = 0;
auto off = lseek(fd, cfg.offset, cfg.whence);
ASSERT_EQ(cfg.ret, off) << "lseek(" << cfg.offset << ", " << cfg.whence << ") failed"
<< (errno ? ": " : "") << (errno ? strerror(errno) : "");
if (off >= dataStart && off < dataEnd) {
off_t dataOff = off - dataStart;
ssize_t readSize = dataSize - dataOff;
uint8_t buf[readSize];
ASSERT_EQ(readSize, TEMP_FAILURE_RETRY(read(fd, buf, readSize)));
EXPECT_EQ(0, memcmp(buf, data + dataOff, readSize));
}
}
EXPECT_EQ(0, munmap(region, dataSize));
}
TEST(AshmemTest, ProtTest) {
unique_fd fd;
constexpr size_t size = PAGE_SIZE;
void *region;
ASSERT_NO_FATAL_FAILURE(TestCreateRegion(size, fd, PROT_READ));
TestProtDenied(fd, size, PROT_WRITE);
TestProtIs(fd, PROT_READ);
ASSERT_NO_FATAL_FAILURE(TestMmap(fd, size, PROT_READ, &region));
EXPECT_EQ(0, munmap(region, size));
ASSERT_NO_FATAL_FAILURE(TestCreateRegion(size, fd, PROT_WRITE));
TestProtDenied(fd, size, PROT_READ);
TestProtIs(fd, PROT_WRITE);
ASSERT_NO_FATAL_FAILURE(TestMmap(fd, size, PROT_WRITE, &region));
EXPECT_EQ(0, munmap(region, size));
ASSERT_NO_FATAL_FAILURE(TestCreateRegion(size, fd, PROT_READ | PROT_WRITE));
TestProtIs(fd, PROT_READ | PROT_WRITE);
ASSERT_EQ(0, ashmem_set_prot_region(fd, PROT_READ));
errno = 0;
ASSERT_EQ(-1, ashmem_set_prot_region(fd, PROT_READ | PROT_WRITE))
<< "kernel shouldn't allow adding protection bits";
EXPECT_EQ(EINVAL, errno);
TestProtIs(fd, PROT_READ);
TestProtDenied(fd, size, PROT_WRITE);
}
TEST(AshmemTest, ForkProtTest) {
unique_fd fd;
constexpr size_t size = PAGE_SIZE;
int protFlags[] = { PROT_READ, PROT_WRITE };
for (int i = 0; i < 2; i++) {
ASSERT_NO_FATAL_FAILURE(TestCreateRegion(size, fd, PROT_READ | PROT_WRITE));
ASSERT_EXIT({
if (ashmem_set_prot_region(fd, protFlags[i]) >= 0) {
_exit(0);
} else {
_exit(1);
}
}, ::testing::ExitedWithCode(0), "");
ASSERT_NO_FATAL_FAILURE(TestProtDenied(fd, size, protFlags[1-i]));
}
}
TEST(AshmemTest, ForkMultiRegionTest) {
constexpr size_t size = PAGE_SIZE;
uint8_t data[size];
FillData(data, size);
constexpr int nRegions = 16;
unique_fd fd[nRegions];
for (int i = 0; i < nRegions; i++) {
ASSERT_NO_FATAL_FAILURE(TestCreateRegion(size, fd[i], PROT_READ | PROT_WRITE));
void *region;
ASSERT_NO_FATAL_FAILURE(TestMmap(fd[i], size, PROT_READ | PROT_WRITE, &region));
memcpy(region, &data, size);
ASSERT_EQ(0, memcmp(region, &data, size));
EXPECT_EQ(0, munmap(region, size));
}
ASSERT_EXIT({
for (int i = 0; i < nRegions; i++) {
void *region = mmap(nullptr, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd[i], 0);
if (region == MAP_FAILED) {
_exit(1);
}
if (memcmp(region, &data, size) != 0) {
munmap(region, size);
_exit(2);
}
memset(region, 0, size);
munmap(region, size);
}
_exit(0);
}, ::testing::ExitedWithCode(0), "");
memset(&data, 0, size);
for (int i = 0; i < nRegions; i++) {
void *region;
ASSERT_NO_FATAL_FAILURE(TestMmap(fd[i], size, PROT_READ | PROT_WRITE, &region));
ASSERT_EQ(0, memcmp(region, &data, size));
EXPECT_EQ(0, munmap(region, size));
}
}

View file

@ -0,0 +1,181 @@
/*
* Copyright (C) 2014 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.
*/
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <memory>
#include <cutils/memory.h>
#include <gtest/gtest.h>
#define FENCEPOST_LENGTH 8
#define MAX_TEST_SIZE (64*1024)
// Choose values that have no repeating byte values.
#define MEMSET16_PATTERN 0xb139
#define MEMSET32_PATTERN 0x48193a27
enum test_e {
MEMSET16 = 0,
MEMSET32,
};
static int g_memset16_aligns[][2] = {
{ 2, 0 },
{ 4, 0 },
{ 8, 0 },
{ 16, 0 },
{ 32, 0 },
{ 64, 0 },
{ 128, 0 },
{ 4, 2 },
{ 8, 2 },
{ 8, 4 },
{ 8, 6 },
{ 128, 2 },
{ 128, 4 },
{ 128, 6 },
{ 128, 8 },
{ 128, 10 },
{ 128, 12 },
{ 128, 14 },
{ 128, 16 },
};
static int g_memset32_aligns[][2] = {
{ 4, 0 },
{ 8, 0 },
{ 16, 0 },
{ 32, 0 },
{ 64, 0 },
{ 128, 0 },
{ 8, 4 },
{ 128, 4 },
{ 128, 8 },
{ 128, 12 },
{ 128, 16 },
};
static size_t GetIncrement(size_t len, size_t min_incr) {
if (len >= 4096) {
return 1024;
} else if (len >= 1024) {
return 256;
}
return min_incr;
}
// Return a pointer into the current buffer with the specified alignment.
static void *GetAlignedPtr(void *orig_ptr, int alignment, int or_mask) {
uint64_t ptr = reinterpret_cast<uint64_t>(orig_ptr);
if (alignment > 0) {
// When setting the alignment, set it to exactly the alignment chosen.
// The pointer returned will be guaranteed not to be aligned to anything
// more than that.
ptr += alignment - (ptr & (alignment - 1));
ptr |= alignment | or_mask;
}
return reinterpret_cast<void*>(ptr);
}
static void SetFencepost(uint8_t *buffer) {
for (int i = 0; i < FENCEPOST_LENGTH; i += 2) {
buffer[i] = 0xde;
buffer[i+1] = 0xad;
}
}
static void VerifyFencepost(uint8_t *buffer) {
for (int i = 0; i < FENCEPOST_LENGTH; i += 2) {
if (buffer[i] != 0xde || buffer[i+1] != 0xad) {
uint8_t expected_value;
if (buffer[i] == 0xde) {
i++;
expected_value = 0xad;
} else {
expected_value = 0xde;
}
ASSERT_EQ(expected_value, buffer[i]);
}
}
}
void RunMemsetTests(test_e test_type, uint32_t value, int align[][2], size_t num_aligns) {
size_t min_incr = 4;
if (test_type == MEMSET16) {
min_incr = 2;
value |= value << 16;
}
std::unique_ptr<uint32_t[]> expected_buf(new uint32_t[MAX_TEST_SIZE/sizeof(uint32_t)]);
for (size_t i = 0; i < MAX_TEST_SIZE/sizeof(uint32_t); i++) {
expected_buf[i] = value;
}
// Allocate one large buffer with lots of extra space so that we can
// guarantee that all possible alignments will fit.
std::unique_ptr<uint8_t[]> buf(new uint8_t[3*MAX_TEST_SIZE]);
uint8_t *buf_align;
for (size_t i = 0; i < num_aligns; i++) {
size_t incr = min_incr;
for (size_t len = incr; len <= MAX_TEST_SIZE; len += incr) {
incr = GetIncrement(len, min_incr);
buf_align = reinterpret_cast<uint8_t*>(GetAlignedPtr(
buf.get()+FENCEPOST_LENGTH, align[i][0], align[i][1]));
SetFencepost(&buf_align[-FENCEPOST_LENGTH]);
SetFencepost(&buf_align[len]);
memset(buf_align, 0xff, len);
if (test_type == MEMSET16) {
android_memset16(reinterpret_cast<uint16_t*>(buf_align), value, len);
} else {
android_memset32(reinterpret_cast<uint32_t*>(buf_align), value, len);
}
ASSERT_EQ(0, memcmp(expected_buf.get(), buf_align, len))
<< "Failed size " << len << " align " << align[i][0] << " " << align[i][1] << "\n";
VerifyFencepost(&buf_align[-FENCEPOST_LENGTH]);
VerifyFencepost(&buf_align[len]);
}
}
}
TEST(libcutils, android_memset16_non_zero) {
RunMemsetTests(MEMSET16, MEMSET16_PATTERN, g_memset16_aligns, sizeof(g_memset16_aligns)/sizeof(int[2]));
}
TEST(libcutils, android_memset16_zero) {
RunMemsetTests(MEMSET16, 0, g_memset16_aligns, sizeof(g_memset16_aligns)/sizeof(int[2]));
}
TEST(libcutils, android_memset32_non_zero) {
RunMemsetTests(MEMSET32, MEMSET32_PATTERN, g_memset32_aligns, sizeof(g_memset32_aligns)/sizeof(int[2]));
}
TEST(libcutils, android_memset32_zero) {
RunMemsetTests(MEMSET32, 0, g_memset32_aligns, sizeof(g_memset32_aligns)/sizeof(int[2]));
}

View file

@ -0,0 +1,360 @@
/*
* Copyright (C) 2014 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 "Properties_test"
#include <limits.h>
#include <iostream>
#include <sstream>
#include <string>
#include <android/log.h>
#include <android-base/macros.h>
#include <cutils/properties.h>
#include <gtest/gtest.h>
namespace android {
#define STRINGIFY_INNER(x) #x
#define STRINGIFY(x) STRINGIFY_INNER(x)
#define ASSERT_OK(x) ASSERT_EQ(0, (x))
#define EXPECT_OK(x) EXPECT_EQ(0, (x))
#define PROPERTY_TEST_KEY "libcutils.test.key"
#define PROPERTY_TEST_VALUE_DEFAULT "<<<default_value>>>"
template <typename T>
static std::string HexString(T value) {
std::stringstream ss;
ss << "0x" << std::hex << std::uppercase << value;
return ss.str();
}
template <typename T>
static ::testing::AssertionResult AssertEqualHex(const char *mExpr,
const char *nExpr,
T m,
T n) {
if (m == n) {
return ::testing::AssertionSuccess();
}
return ::testing::AssertionFailure()
<< mExpr << " and " << nExpr << " (expected: " << HexString(m) <<
", actual: " << HexString(n) << ") are not equal";
}
class PropertiesTest : public testing::Test {
public:
PropertiesTest() : mValue() {}
protected:
virtual void SetUp() {
EXPECT_OK(property_set(PROPERTY_TEST_KEY, /*value*/NULL));
}
virtual void TearDown() {
EXPECT_OK(property_set(PROPERTY_TEST_KEY, /*value*/NULL));
}
char mValue[PROPERTY_VALUE_MAX];
template <typename T>
static std::string ToString(T value) {
std::stringstream ss;
ss << value;
return ss.str();
}
// Return length of property read; value is written into mValue
int SetAndGetProperty(const char* value, const char* defaultValue = PROPERTY_TEST_VALUE_DEFAULT) {
EXPECT_OK(property_set(PROPERTY_TEST_KEY, value)) << "value: '" << value << "'";
return property_get(PROPERTY_TEST_KEY, mValue, defaultValue);
}
void ResetValue(unsigned char c = 0xFF) {
for (size_t i = 0; i < arraysize(mValue); ++i) {
mValue[i] = (char) c;
}
}
};
TEST_F(PropertiesTest, SetString) {
// Null key -> unsuccessful set
{
// Null key -> fails
EXPECT_GT(0, property_set(/*key*/NULL, PROPERTY_TEST_VALUE_DEFAULT));
}
// Null value -> returns default value
{
// Null value -> OK , and it clears the value
EXPECT_OK(property_set(PROPERTY_TEST_KEY, /*value*/NULL));
ResetValue();
// Since the value is null, default value will be returned
size_t len = property_get(PROPERTY_TEST_KEY, mValue, PROPERTY_TEST_VALUE_DEFAULT);
EXPECT_EQ(strlen(PROPERTY_TEST_VALUE_DEFAULT), len);
EXPECT_STREQ(PROPERTY_TEST_VALUE_DEFAULT, mValue);
}
// Trivial case => get returns what was set
{
size_t len = SetAndGetProperty("hello_world");
EXPECT_EQ(strlen("hello_world"), len) << "hello_world key";
EXPECT_STREQ("hello_world", mValue);
ResetValue();
}
// Set to empty string => get returns default always
{
const char* EMPTY_STRING_DEFAULT = "EMPTY_STRING";
size_t len = SetAndGetProperty("", EMPTY_STRING_DEFAULT);
EXPECT_EQ(strlen(EMPTY_STRING_DEFAULT), len) << "empty key";
EXPECT_STREQ(EMPTY_STRING_DEFAULT, mValue);
ResetValue();
}
// Set to max length => get returns what was set
{
std::string maxLengthString = std::string(PROPERTY_VALUE_MAX-1, 'a');
int len = SetAndGetProperty(maxLengthString.c_str());
EXPECT_EQ(PROPERTY_VALUE_MAX-1, len) << "max length key";
EXPECT_STREQ(maxLengthString.c_str(), mValue);
ResetValue();
}
// Set to max length + 1 => set fails
{
const char* VALID_TEST_VALUE = "VALID_VALUE";
ASSERT_OK(property_set(PROPERTY_TEST_KEY, VALID_TEST_VALUE));
std::string oneLongerString = std::string(PROPERTY_VALUE_MAX, 'a');
// Expect that the value set fails since it's too long
EXPECT_GT(0, property_set(PROPERTY_TEST_KEY, oneLongerString.c_str()));
size_t len = property_get(PROPERTY_TEST_KEY, mValue, PROPERTY_TEST_VALUE_DEFAULT);
EXPECT_EQ(strlen(VALID_TEST_VALUE), len) << "set should've failed";
EXPECT_STREQ(VALID_TEST_VALUE, mValue);
ResetValue();
}
}
TEST_F(PropertiesTest, GetString) {
// Try to use a default value that's too long => get truncates the value
{
ASSERT_OK(property_set(PROPERTY_TEST_KEY, ""));
std::string maxLengthString = std::string(PROPERTY_VALUE_MAX - 1, 'a');
std::string oneLongerString = std::string(PROPERTY_VALUE_MAX, 'a');
// Expect that the value is truncated since it's too long (by 1)
int len = property_get(PROPERTY_TEST_KEY, mValue, oneLongerString.c_str());
EXPECT_EQ(PROPERTY_VALUE_MAX - 1, len);
EXPECT_STREQ(maxLengthString.c_str(), mValue);
ResetValue();
}
// Try to use a default value that's the max length => get succeeds
{
ASSERT_OK(property_set(PROPERTY_TEST_KEY, ""));
std::string maxLengthString = std::string(PROPERTY_VALUE_MAX - 1, 'b');
// Expect that the value matches maxLengthString
int len = property_get(PROPERTY_TEST_KEY, mValue, maxLengthString.c_str());
EXPECT_EQ(PROPERTY_VALUE_MAX - 1, len);
EXPECT_STREQ(maxLengthString.c_str(), mValue);
ResetValue();
}
// Try to use a default value of length one => get succeeds
{
ASSERT_OK(property_set(PROPERTY_TEST_KEY, ""));
std::string oneCharString = std::string(1, 'c');
// Expect that the value matches oneCharString
int len = property_get(PROPERTY_TEST_KEY, mValue, oneCharString.c_str());
EXPECT_EQ(1, len);
EXPECT_STREQ(oneCharString.c_str(), mValue);
ResetValue();
}
// Try to use a default value of length zero => get succeeds
{
ASSERT_OK(property_set(PROPERTY_TEST_KEY, ""));
std::string zeroCharString = std::string(0, 'd');
// Expect that the value matches oneCharString
int len = property_get(PROPERTY_TEST_KEY, mValue, zeroCharString.c_str());
EXPECT_EQ(0, len);
EXPECT_STREQ(zeroCharString.c_str(), mValue);
ResetValue();
}
// Try to use a NULL default value => get returns 0
{
ASSERT_OK(property_set(PROPERTY_TEST_KEY, ""));
// Expect a return value of 0
int len = property_get(PROPERTY_TEST_KEY, mValue, NULL);
EXPECT_EQ(0, len);
ResetValue();
}
}
TEST_F(PropertiesTest, GetBool) {
/**
* TRUE
*/
const char *valuesTrue[] = { "1", "true", "y", "yes", "on", };
for (size_t i = 0; i < arraysize(valuesTrue); ++i) {
ASSERT_OK(property_set(PROPERTY_TEST_KEY, valuesTrue[i]));
bool val = property_get_bool(PROPERTY_TEST_KEY, /*default_value*/false);
EXPECT_TRUE(val) << "Property should've been TRUE for value: '" << valuesTrue[i] << "'";
}
/**
* FALSE
*/
const char *valuesFalse[] = { "0", "false", "n", "no", "off", };
for (size_t i = 0; i < arraysize(valuesFalse); ++i) {
ASSERT_OK(property_set(PROPERTY_TEST_KEY, valuesFalse[i]));
bool val = property_get_bool(PROPERTY_TEST_KEY, /*default_value*/true);
EXPECT_FALSE(val) << "Property shoud've been FALSE For string value: '" << valuesFalse[i] << "'";
}
/**
* NEITHER
*/
const char *valuesNeither[] = { "x0", "x1", "2", "-2", "True", "False", "garbage", "", " ",
"+1", " 1 ", " true", " true ", " y ", " yes", "yes ",
"+0", "-0", "00", " 00 ", " false", "false ",
};
for (size_t i = 0; i < arraysize(valuesNeither); ++i) {
ASSERT_OK(property_set(PROPERTY_TEST_KEY, valuesNeither[i]));
// The default value should always be used
bool val = property_get_bool(PROPERTY_TEST_KEY, /*default_value*/true);
EXPECT_TRUE(val) << "Property should've been NEITHER (true) for string value: '" << valuesNeither[i] << "'";
val = property_get_bool(PROPERTY_TEST_KEY, /*default_value*/false);
EXPECT_FALSE(val) << "Property should've been NEITHER (false) for string value: '" << valuesNeither[i] << "'";
}
}
TEST_F(PropertiesTest, GetInt64) {
const int64_t DEFAULT_VALUE = INT64_C(0xDEADBEEFBEEFDEAD);
const std::string longMaxString = ToString(INT64_MAX);
const std::string longStringOverflow = longMaxString + "0";
const std::string longMinString = ToString(INT64_MIN);
const std::string longStringUnderflow = longMinString + "0";
const char* setValues[] = {
// base 10
"1", "2", "12345", "-1", "-2", "-12345",
// base 16
"0xFF", "0x0FF", "0xC0FFEE",
// base 8
"0", "01234", "07",
// corner cases
" 2", "2 ", "+0", "-0", " +0 ", longMaxString.c_str(), longMinString.c_str(),
// failing cases
NULL, "", " ", " ", "hello", " true ", "y",
longStringOverflow.c_str(), longStringUnderflow.c_str(),
};
int64_t getValues[] = {
// base 10
1, 2, 12345, -1, -2, -12345,
// base 16
0xFF, 0x0FF, 0xC0FFEE,
// base 8
0, 01234, 07,
// corner cases
2, 2, 0, 0, 0, INT64_MAX, INT64_MIN,
// failing cases
DEFAULT_VALUE, DEFAULT_VALUE, DEFAULT_VALUE, DEFAULT_VALUE, DEFAULT_VALUE, DEFAULT_VALUE, DEFAULT_VALUE,
DEFAULT_VALUE, DEFAULT_VALUE,
};
ASSERT_EQ(arraysize(setValues), arraysize(getValues));
for (size_t i = 0; i < arraysize(setValues); ++i) {
ASSERT_OK(property_set(PROPERTY_TEST_KEY, setValues[i]));
int64_t val = property_get_int64(PROPERTY_TEST_KEY, DEFAULT_VALUE);
EXPECT_PRED_FORMAT2(AssertEqualHex, getValues[i], val) << "Property was set to '" << setValues[i] << "'";
}
}
TEST_F(PropertiesTest, GetInt32) {
const int32_t DEFAULT_VALUE = INT32_C(0xDEADBEEF);
const std::string intMaxString = ToString(INT32_MAX);
const std::string intStringOverflow = intMaxString + "0";
const std::string intMinString = ToString(INT32_MIN);
const std::string intStringUnderflow = intMinString + "0";
const char* setValues[] = {
// base 10
"1", "2", "12345", "-1", "-2", "-12345",
// base 16
"0xFF", "0x0FF", "0xC0FFEE", "0Xf00",
// base 8
"0", "01234", "07",
// corner cases
" 2", "2 ", "+0", "-0", " +0 ", intMaxString.c_str(), intMinString.c_str(),
// failing cases
NULL, "", " ", " ", "hello", " true ", "y",
intStringOverflow.c_str(), intStringUnderflow.c_str(),
};
int32_t getValues[] = {
// base 10
1, 2, 12345, -1, -2, -12345,
// base 16
0xFF, 0x0FF, 0xC0FFEE, 0Xf00,
// base 8
0, 01234, 07,
// corner cases
2, 2, 0, 0, 0, INT32_MAX, INT32_MIN,
// failing cases
DEFAULT_VALUE, DEFAULT_VALUE, DEFAULT_VALUE, DEFAULT_VALUE, DEFAULT_VALUE, DEFAULT_VALUE, DEFAULT_VALUE,
DEFAULT_VALUE, DEFAULT_VALUE,
};
ASSERT_EQ(arraysize(setValues), arraysize(getValues));
for (size_t i = 0; i < arraysize(setValues); ++i) {
ASSERT_OK(property_set(PROPERTY_TEST_KEY, setValues[i]));
int32_t val = property_get_int32(PROPERTY_TEST_KEY, DEFAULT_VALUE);
EXPECT_PRED_FORMAT2(AssertEqualHex, getValues[i], val) << "Property was set to '" << setValues[i] << "'";
}
}
} // namespace android

View file

@ -0,0 +1,50 @@
/*
* Copyright (C) 2016 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.
*/
#include <ctype.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <time.h>
#include <string>
#include <android-base/stringprintf.h>
#include <android-base/test_utils.h>
#include <cutils/android_get_control_file.h>
#include <gtest/gtest.h>
TEST(FilesTest, android_get_control_file) {
TemporaryFile tf;
ASSERT_GE(tf.fd, 0);
std::string key(ANDROID_FILE_ENV_PREFIX);
key += tf.path;
std::for_each(key.begin(), key.end(), [] (char& c) { c = isalnum(c) ? c : '_'; });
EXPECT_EQ(unsetenv(key.c_str()), 0);
EXPECT_EQ(android_get_control_file(tf.path), -1);
EXPECT_EQ(setenv(key.c_str(), android::base::StringPrintf("%d", tf.fd).c_str(), true), 0);
EXPECT_EQ(android_get_control_file(tf.path), tf.fd);
close(tf.fd);
EXPECT_EQ(android_get_control_file(tf.path), -1);
EXPECT_EQ(unsetenv(key.c_str()), 0);
EXPECT_EQ(android_get_control_file(tf.path), -1);
}

View file

@ -0,0 +1,71 @@
/*
* Copyright (C) 2016 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.
*/
#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/un.h>
#include <time.h>
#include <cutils/sockets.h>
#include <gtest/gtest.h>
#ifndef SOCK_NONBLOCK
#define SOCK_NONBLOCK 0
#endif
#ifndef SOCK_CLOEXEC
#define SOCK_CLOEXEC 0
#endif
TEST(SocketsTest, android_get_control_socket) {
static const char key[] = ANDROID_SOCKET_ENV_PREFIX "SocketsTest_android_get_control_socket";
static const char* name = key + strlen(ANDROID_SOCKET_ENV_PREFIX);
EXPECT_EQ(unsetenv(key), 0);
EXPECT_EQ(android_get_control_socket(name), -1);
int fd;
ASSERT_GE(fd = socket(PF_UNIX, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0), 0);
#ifdef F_GETFL
int flags;
ASSERT_GE(flags = fcntl(fd, F_GETFL), 0);
ASSERT_GE(fcntl(fd, F_SETFL, flags | O_NONBLOCK), 0);
#endif
EXPECT_EQ(android_get_control_socket(name), -1);
struct sockaddr_un addr;
memset(&addr, 0, sizeof(addr));
addr.sun_family = AF_UNIX;
snprintf(addr.sun_path, sizeof(addr.sun_path), ANDROID_SOCKET_DIR"/%s", name);
unlink(addr.sun_path);
EXPECT_EQ(bind(fd, (struct sockaddr*)&addr, sizeof(addr)), 0);
EXPECT_EQ(android_get_control_socket(name), -1);
char val[32];
snprintf(val, sizeof(val), "%d", fd);
EXPECT_EQ(setenv(key, val, true), 0);
EXPECT_EQ(android_get_control_socket(name), fd);
socket_close(fd);
EXPECT_EQ(android_get_control_socket(name), -1);
EXPECT_EQ(unlink(addr.sun_path), 0);
EXPECT_EQ(android_get_control_socket(name), -1);
EXPECT_EQ(unsetenv(key), 0);
EXPECT_EQ(android_get_control_socket(name), -1);
}

View file

@ -0,0 +1,248 @@
/*
* Copyright (C) 2017 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.
*/
#include <inttypes.h>
#include <string>
#include <gtest/gtest.h>
#include <android-base/file.h>
#include <android-base/stringprintf.h>
#include <android-base/strings.h>
#include <private/android_filesystem_config.h>
#include <private/fs_config.h>
extern const fs_path_config* __for_testing_only__android_dirs;
extern const fs_path_config* __for_testing_only__android_files;
extern bool (*__for_testing_only__fs_config_cmp)(bool, const char*, size_t, const char*, size_t);
// Maximum entries in system/core/libcutils/fs_config.cpp:android_* before we
// hit a nullptr termination, before we declare the list is just too big or
// could be missing the nullptr.
static constexpr size_t max_idx = 4096;
static const struct fs_config_cmp_test {
bool dir;
const char* prefix;
const char* path;
bool match;
} fs_config_cmp_tests[] = {
// clang-format off
{ true, "system/lib", "system/lib/hw", true },
{ true, "vendor/lib", "system/vendor/lib/hw", true },
{ true, "system/vendor/lib", "vendor/lib/hw", true },
{ true, "system/vendor/lib", "system/vendor/lib/hw", true },
{ false, "vendor/bin/wifi", "system/vendor/bin/w", false },
{ false, "vendor/bin/wifi", "system/vendor/bin/wifi", true },
{ false, "vendor/bin/wifi", "system/vendor/bin/wifi2", false },
{ false, "system/vendor/bin/wifi", "system/vendor/bin/wifi", true, },
{ false, "odm/bin/wifi", "system/odm/bin/wifi", true },
{ false, "oem/bin/wifi", "system/oem/bin/wifi", true },
{ false, "data/bin/wifi", "system/data/bin/wifi", false },
{ false, "system/bin/*", "system/bin/wifi", true },
{ false, "vendor/bin/*", "system/vendor/bin/wifi", true },
{ false, "system/bin/*", "system/bin", false },
{ false, "system/vendor/bin/*", "vendor/bin/wifi", true },
{ false, NULL, NULL, false },
// clang-format on
};
static bool check_unique(std::vector<const char*>& paths, const std::string& config_name,
const std::string& prefix) {
bool retval = false;
std::string alternate = "system/" + prefix;
for (size_t idx = 0; idx < paths.size(); ++idx) {
size_t second;
std::string path(paths[idx]);
// check if there are multiple identical paths
for (second = idx + 1; second < paths.size(); ++second) {
if (path == paths[second]) {
GTEST_LOG_(ERROR) << "duplicate paths in " << config_name << ": " << paths[idx];
retval = true;
break;
}
}
// check if path is <partition>/
if (android::base::StartsWith(path, prefix.c_str())) {
// rebuild path to be system/<partition>/... to check for alias
path = alternate + path.substr(prefix.size());
for (second = 0; second < paths.size(); ++second) {
if (path == paths[second]) {
GTEST_LOG_(ERROR) << "duplicate alias paths in " << config_name << ": "
<< paths[idx] << " and " << paths[second]
<< " (remove latter)";
retval = true;
break;
}
}
continue;
}
// check if path is system/<partition>/
if (android::base::StartsWith(path, alternate.c_str())) {
// rebuild path to be <partition>/... to check for alias
path = prefix + path.substr(alternate.size());
for (second = 0; second < paths.size(); ++second) {
if (path == paths[second]) break;
}
if (second >= paths.size()) {
GTEST_LOG_(ERROR) << "replace path in " << config_name << ": " << paths[idx]
<< " with " << path;
retval = true;
}
}
}
return retval;
}
static bool check_unique(const fs_path_config* paths, const char* type_name,
const std::string& prefix) {
std::string config("system/core/libcutils/fs_config.cpp:android_");
config += type_name;
config += "[]";
bool retval = false;
std::vector<const char*> paths_tmp;
for (size_t idx = 0; paths[idx].prefix; ++idx) {
if (idx > max_idx) {
GTEST_LOG_(WARNING) << config << ": has no end (missing null prefix)";
retval = true;
break;
}
paths_tmp.push_back(paths[idx].prefix);
}
return check_unique(paths_tmp, config, prefix) || retval;
}
static bool check_fs_config_cmp(const fs_config_cmp_test* tests) {
bool match, retval = false;
for (size_t idx = 0; tests[idx].prefix; ++idx) {
match = __for_testing_only__fs_config_cmp(tests[idx].dir, tests[idx].prefix,
strlen(tests[idx].prefix), tests[idx].path,
strlen(tests[idx].path));
if (match != tests[idx].match) {
GTEST_LOG_(ERROR) << tests[idx].path << (match ? " matched " : " didn't match ")
<< tests[idx].prefix;
retval = true;
break;
}
}
return retval;
}
#define endof(pointer, field) (offsetof(typeof(*(pointer)), field) + sizeof((pointer)->field))
static bool check_unique(const std::string& config, const std::string& prefix) {
int retval = false;
std::string data;
if (!android::base::ReadFileToString(config, &data)) return retval;
const fs_path_config_from_file* pc =
reinterpret_cast<const fs_path_config_from_file*>(data.c_str());
size_t len = data.size();
std::vector<const char*> paths_tmp;
size_t entry_number = 0;
while (len > 0) {
uint16_t host_len = (len >= endof(pc, len)) ? pc->len : INT16_MAX;
if (host_len > len) {
GTEST_LOG_(WARNING) << config << ": truncated at entry " << entry_number << " ("
<< host_len << " > " << len << ")";
const std::string unknown("?");
GTEST_LOG_(WARNING)
<< config << ": entry[" << entry_number << "]={ "
<< "len=" << ((len >= endof(pc, len))
? android::base::StringPrintf("%" PRIu16, pc->len)
: unknown)
<< ", mode=" << ((len >= endof(pc, mode))
? android::base::StringPrintf("0%" PRIo16, pc->mode)
: unknown)
<< ", uid=" << ((len >= endof(pc, uid))
? android::base::StringPrintf("%" PRIu16, pc->uid)
: unknown)
<< ", gid=" << ((len >= endof(pc, gid))
? android::base::StringPrintf("%" PRIu16, pc->gid)
: unknown)
<< ", capabilities="
<< ((len >= endof(pc, capabilities))
? android::base::StringPrintf("0x%" PRIx64, pc->capabilities)
: unknown)
<< ", prefix="
<< ((len >= offsetof(fs_path_config_from_file, prefix))
? android::base::StringPrintf(
"\"%.*s...", (int)(len - offsetof(fs_path_config_from_file, prefix)),
pc->prefix)
: unknown)
<< " }";
retval = true;
break;
}
paths_tmp.push_back(pc->prefix);
pc = reinterpret_cast<const fs_path_config_from_file*>(reinterpret_cast<const char*>(pc) +
host_len);
len -= host_len;
++entry_number;
}
return check_unique(paths_tmp, config, prefix) || retval;
}
void check_two(const fs_path_config* paths, const char* type_name, const char* prefix) {
ASSERT_FALSE(paths == nullptr);
ASSERT_FALSE(type_name == nullptr);
ASSERT_FALSE(prefix == nullptr);
bool check_internal = check_unique(paths, type_name, prefix);
EXPECT_FALSE(check_internal);
bool check_overrides =
check_unique(std::string("/") + prefix + "etc/fs_config_" + type_name, prefix);
EXPECT_FALSE(check_overrides);
}
TEST(fs_config, vendor_dirs_alias) {
check_two(__for_testing_only__android_dirs, "dirs", "vendor/");
}
TEST(fs_config, vendor_files_alias) {
check_two(__for_testing_only__android_files, "files", "vendor/");
}
TEST(fs_config, oem_dirs_alias) {
check_two(__for_testing_only__android_dirs, "dirs", "oem/");
}
TEST(fs_config, oem_files_alias) {
check_two(__for_testing_only__android_files, "files", "oem/");
}
TEST(fs_config, odm_dirs_alias) {
check_two(__for_testing_only__android_dirs, "dirs", "odm/");
}
TEST(fs_config, odm_files_alias) {
check_two(__for_testing_only__android_files, "files", "odm/");
}
TEST(fs_config, system_alias) {
EXPECT_FALSE(check_fs_config_cmp(fs_config_cmp_tests));
}

View file

@ -0,0 +1,91 @@
/*
* Copyright (C) 2016 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.
*/
#include <cutils/multiuser.h>
#include <gtest/gtest.h>
static constexpr auto ERR_GID = static_cast<gid_t>(-1);
TEST(MultiuserTest, TestMerge) {
EXPECT_EQ(0U, multiuser_get_uid(0, 0));
EXPECT_EQ(1000U, multiuser_get_uid(0, 1000));
EXPECT_EQ(10000U, multiuser_get_uid(0, 10000));
EXPECT_EQ(50000U, multiuser_get_uid(0, 50000));
EXPECT_EQ(1000000U, multiuser_get_uid(10, 0));
EXPECT_EQ(1001000U, multiuser_get_uid(10, 1000));
EXPECT_EQ(1010000U, multiuser_get_uid(10, 10000));
EXPECT_EQ(1050000U, multiuser_get_uid(10, 50000));
}
TEST(MultiuserTest, TestSplitUser) {
EXPECT_EQ(0U, multiuser_get_user_id(0));
EXPECT_EQ(0U, multiuser_get_user_id(1000));
EXPECT_EQ(0U, multiuser_get_user_id(10000));
EXPECT_EQ(0U, multiuser_get_user_id(50000));
EXPECT_EQ(10U, multiuser_get_user_id(1000000));
EXPECT_EQ(10U, multiuser_get_user_id(1001000));
EXPECT_EQ(10U, multiuser_get_user_id(1010000));
EXPECT_EQ(10U, multiuser_get_user_id(1050000));
}
TEST(MultiuserTest, TestSplitApp) {
EXPECT_EQ(0U, multiuser_get_app_id(0));
EXPECT_EQ(1000U, multiuser_get_app_id(1000));
EXPECT_EQ(10000U, multiuser_get_app_id(10000));
EXPECT_EQ(50000U, multiuser_get_app_id(50000));
EXPECT_EQ(0U, multiuser_get_app_id(1000000));
EXPECT_EQ(1000U, multiuser_get_app_id(1001000));
EXPECT_EQ(10000U, multiuser_get_app_id(1010000));
EXPECT_EQ(50000U, multiuser_get_app_id(1050000));
}
TEST(MultiuserTest, TestCache) {
EXPECT_EQ(ERR_GID, multiuser_get_cache_gid(0, 0));
EXPECT_EQ(ERR_GID, multiuser_get_cache_gid(0, 1000));
EXPECT_EQ(20000U, multiuser_get_cache_gid(0, 10000));
EXPECT_EQ(ERR_GID, multiuser_get_cache_gid(0, 50000));
EXPECT_EQ(ERR_GID, multiuser_get_cache_gid(10, 0));
EXPECT_EQ(ERR_GID, multiuser_get_cache_gid(10, 1000));
EXPECT_EQ(1020000U, multiuser_get_cache_gid(10, 10000));
EXPECT_EQ(ERR_GID, multiuser_get_cache_gid(10, 50000));
}
TEST(MultiuserTest, TestExt) {
EXPECT_EQ(ERR_GID, multiuser_get_ext_gid(0, 0));
EXPECT_EQ(ERR_GID, multiuser_get_ext_gid(0, 1000));
EXPECT_EQ(30000U, multiuser_get_ext_gid(0, 10000));
EXPECT_EQ(ERR_GID, multiuser_get_ext_gid(0, 50000));
EXPECT_EQ(1030000U, multiuser_get_ext_gid(10, 10000));
}
TEST(MultiuserTest, TestExtCache) {
EXPECT_EQ(ERR_GID, multiuser_get_ext_cache_gid(0, 0));
EXPECT_EQ(ERR_GID, multiuser_get_ext_cache_gid(0, 1000));
EXPECT_EQ(40000U, multiuser_get_ext_cache_gid(0, 10000));
EXPECT_EQ(ERR_GID, multiuser_get_ext_cache_gid(0, 50000));
EXPECT_EQ(1040000U, multiuser_get_ext_cache_gid(10, 10000));
}
TEST(MultiuserTest, TestShared) {
EXPECT_EQ(0U, multiuser_get_shared_gid(0, 0));
EXPECT_EQ(1000U, multiuser_get_shared_gid(0, 1000));
EXPECT_EQ(50000U, multiuser_get_shared_gid(0, 10000));
EXPECT_EQ(ERR_GID, multiuser_get_shared_gid(0, 50000));
EXPECT_EQ(0U, multiuser_get_shared_gid(10, 0));
EXPECT_EQ(1000U, multiuser_get_shared_gid(10, 1000));
EXPECT_EQ(50000U, multiuser_get_shared_gid(10, 10000));
EXPECT_EQ(ERR_GID, multiuser_get_shared_gid(10, 50000));
}

View file

@ -0,0 +1,98 @@
/*
* Copyright (C) 2016 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.
*/
#include <algorithm>
#include <chrono>
#include <thread>
#include <vector>
#include <sys/capability.h>
#include <cutils/sched_policy.h>
#include <gtest/gtest.h>
bool hasCapSysNice() {
__user_cap_header_struct header;
memset(&header, 0, sizeof(header));
header.version = _LINUX_CAPABILITY_VERSION_3;
__user_cap_data_struct caps[_LINUX_CAPABILITY_U32S_3];
if (capget(&header, &caps[0])) {
GTEST_LOG_(WARNING) << "failed to get process capabilities";
return false;
}
auto nice_idx = CAP_TO_INDEX(CAP_SYS_NICE);
auto nice_mask = CAP_TO_MASK(CAP_SYS_NICE);
return caps[nice_idx].effective & nice_mask;
}
long long medianSleepTime() {
std::vector<long long> sleepTimes;
constexpr size_t numSamples = 100;
for (size_t i = 0; i < numSamples; i++) {
auto start = std::chrono::steady_clock::now();
std::this_thread::sleep_for(std::chrono::nanoseconds(1));
auto end = std::chrono::steady_clock::now();
auto diff = end - start;
sleepTimes.push_back(diff.count());
}
constexpr auto median = numSamples / 2;
std::nth_element(sleepTimes.begin(), sleepTimes.begin() + median,
sleepTimes.end());
return sleepTimes[median];
}
TEST(SchedPolicy, set_sched_policy) {
if (!hasCapSysNice()) {
GTEST_LOG_(INFO) << "skipping test that requires CAP_SYS_NICE";
return;
}
// A measureable effect of scheduling policy is that the kernel has 800x
// greater slack time in waking up a sleeping background thread.
//
// Look for 100x difference in how long FB and BG threads actually sleep
// when trying to sleep for 1 ns. This difference is large enough not
// to happen by chance, but small enough (compared to 800x) to keep inherent
// fuzziness in scheduler behavior from causing false negatives.
const unsigned int BG_FG_SLACK_FACTOR = 100;
ASSERT_EQ(0, set_sched_policy(0, SP_BACKGROUND));
auto bgSleepTime = medianSleepTime();
ASSERT_EQ(0, set_sched_policy(0, SP_FOREGROUND));
auto fgSleepTime = medianSleepTime();
ASSERT_GT(bgSleepTime, fgSleepTime * BG_FG_SLACK_FACTOR);
}
TEST(SchedPolicy, get_sched_policy) {
SchedPolicy policy;
ASSERT_EQ(0, get_sched_policy(0, &policy));
const char *policyName = get_sched_policy_name(policy);
EXPECT_NE(nullptr, policyName);
EXPECT_STRNE("error", policyName);
ASSERT_EQ(0, set_sched_policy(0, SP_BACKGROUND));
SchedPolicy newPolicy;
ASSERT_EQ(0, get_sched_policy(0, &newPolicy));
EXPECT_EQ(SP_BACKGROUND, newPolicy);
}

View file

@ -0,0 +1,189 @@
/*
* Copyright (C) 2015 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.
*/
// Tests socket functionality using loopback connections. Requires IPv4 and
// IPv6 capabilities. These tests assume that no UDP packets are lost, which
// should be the case for loopback communication, but is not guaranteed.
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <time.h>
#include <cutils/sockets.h>
#include <gtest/gtest.h>
// Makes sure the passed sockets are valid, sends data between them, and closes
// them. Any failures are logged with gtest.
//
// On Mac recvfrom() will not fill in the address for TCP sockets, so we need
// separate logic paths depending on socket type.
static void TestConnectedSockets(cutils_socket_t server, cutils_socket_t client,
int type) {
ASSERT_NE(INVALID_SOCKET, server);
ASSERT_NE(INVALID_SOCKET, client);
char buffer[128];
sockaddr_storage addr;
socklen_t addr_size = sizeof(addr);
// Send client -> server first to get the UDP client's address.
ASSERT_EQ(3, send(client, "foo", 3, 0));
if (type == SOCK_DGRAM) {
EXPECT_EQ(3, recvfrom(server, buffer, sizeof(buffer), 0,
reinterpret_cast<sockaddr*>(&addr), &addr_size));
} else {
EXPECT_EQ(3, recv(server, buffer, sizeof(buffer), 0));
}
EXPECT_EQ(0, memcmp(buffer, "foo", 3));
// Now send server -> client.
if (type == SOCK_DGRAM) {
ASSERT_EQ(3, sendto(server, "bar", 3, 0,
reinterpret_cast<sockaddr*>(&addr), addr_size));
} else {
ASSERT_EQ(3, send(server, "bar", 3, 0));
}
EXPECT_EQ(3, recv(client, buffer, sizeof(buffer), 0));
EXPECT_EQ(0, memcmp(buffer, "bar", 3));
// Send multiple buffers using socket_send_buffers().
std::string data[] = {"foo", "bar", "12345"};
cutils_socket_buffer_t socket_buffers[] = { {data[0].data(), data[0].length()},
{data[1].data(), data[1].length()},
{data[2].data(), data[2].length()} };
EXPECT_EQ(11, socket_send_buffers(client, socket_buffers, 3));
EXPECT_EQ(11, recv(server, buffer, sizeof(buffer), 0));
EXPECT_EQ(0, memcmp(buffer, "foobar12345", 11));
EXPECT_EQ(0, socket_close(server));
EXPECT_EQ(0, socket_close(client));
}
// Tests receive timeout. The timing verification logic must be very coarse to
// make sure different systems can all pass these tests.
void TestReceiveTimeout(cutils_socket_t sock) {
time_t start_time;
char buffer[32];
// Make sure a 20ms timeout completes in 1 second or less.
EXPECT_EQ(0, socket_set_receive_timeout(sock, 20));
start_time = time(nullptr);
EXPECT_EQ(-1, recv(sock, buffer, sizeof(buffer), 0));
EXPECT_LE(difftime(time(nullptr), start_time), 1.0);
// Make sure a 1250ms timeout takes 1 second or more.
EXPECT_EQ(0, socket_set_receive_timeout(sock, 1250));
start_time = time(nullptr);
EXPECT_EQ(-1, recv(sock, buffer, sizeof(buffer), 0));
EXPECT_LE(1.0, difftime(time(nullptr), start_time));
}
// Tests socket_get_local_port().
TEST(SocketsTest, TestGetLocalPort) {
cutils_socket_t server;
// Check a bunch of ports so that we can ignore any conflicts in case
// of ports already being taken, but if a server is able to start up we
// should always be able to read its port.
for (int port : {10000, 12345, 15999, 20202, 25000}) {
for (int type : {SOCK_DGRAM, SOCK_STREAM}) {
server = socket_inaddr_any_server(port, type);
if (server != INVALID_SOCKET) {
EXPECT_EQ(port, socket_get_local_port(server));
}
socket_close(server);
}
}
// Check expected failure for an invalid socket.
EXPECT_EQ(-1, socket_get_local_port(INVALID_SOCKET));
}
// Tests socket_inaddr_any_server() and socket_network_client() for IPv4 UDP.
TEST(SocketsTest, TestIpv4UdpLoopback) {
cutils_socket_t server = socket_inaddr_any_server(0, SOCK_DGRAM);
cutils_socket_t client = socket_network_client(
"127.0.0.1", socket_get_local_port(server), SOCK_DGRAM);
TestConnectedSockets(server, client, SOCK_DGRAM);
}
// Tests socket_inaddr_any_server() and socket_network_client() for IPv4 TCP.
TEST(SocketsTest, TestIpv4TcpLoopback) {
cutils_socket_t server = socket_inaddr_any_server(0, SOCK_STREAM);
ASSERT_NE(INVALID_SOCKET, server);
cutils_socket_t client = socket_network_client(
"127.0.0.1", socket_get_local_port(server), SOCK_STREAM);
cutils_socket_t handler = accept(server, nullptr, nullptr);
EXPECT_EQ(0, socket_close(server));
TestConnectedSockets(handler, client, SOCK_STREAM);
}
// Tests socket_inaddr_any_server() and socket_network_client() for IPv6 UDP.
TEST(SocketsTest, TestIpv6UdpLoopback) {
cutils_socket_t server = socket_inaddr_any_server(0, SOCK_DGRAM);
cutils_socket_t client = socket_network_client(
"::1", socket_get_local_port(server), SOCK_DGRAM);
TestConnectedSockets(server, client, SOCK_DGRAM);
}
// Tests socket_inaddr_any_server() and socket_network_client() for IPv6 TCP.
TEST(SocketsTest, TestIpv6TcpLoopback) {
cutils_socket_t server = socket_inaddr_any_server(0, SOCK_STREAM);
ASSERT_NE(INVALID_SOCKET, server);
cutils_socket_t client = socket_network_client(
"::1", socket_get_local_port(server), SOCK_STREAM);
cutils_socket_t handler = accept(server, nullptr, nullptr);
EXPECT_EQ(0, socket_close(server));
TestConnectedSockets(handler, client, SOCK_STREAM);
}
// Tests setting a receive timeout for UDP sockets.
TEST(SocketsTest, TestUdpReceiveTimeout) {
cutils_socket_t sock = socket_inaddr_any_server(0, SOCK_DGRAM);
ASSERT_NE(INVALID_SOCKET, sock);
TestReceiveTimeout(sock);
EXPECT_EQ(0, socket_close(sock));
}
// Tests setting a receive timeout for TCP sockets.
TEST(SocketsTest, TestTcpReceiveTimeout) {
cutils_socket_t server = socket_inaddr_any_server(0, SOCK_STREAM);
ASSERT_NE(INVALID_SOCKET, server);
cutils_socket_t client = socket_network_client(
"localhost", socket_get_local_port(server), SOCK_STREAM);
cutils_socket_t handler = accept(server, nullptr, nullptr);
EXPECT_EQ(0, socket_close(server));
TestReceiveTimeout(handler);
EXPECT_EQ(0, socket_close(client));
EXPECT_EQ(0, socket_close(handler));
}
// Tests socket_send_buffers() failure.
TEST(SocketsTest, TestSocketSendBuffersFailure) {
EXPECT_EQ(-1, socket_send_buffers(INVALID_SOCKET, nullptr, 0));
}

View file

@ -0,0 +1,57 @@
/*
* Copyright (C) 2011 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.
*/
#include <cutils/str_parms.h>
#include <gtest/gtest.h>
static void test_str_parms_str(const char* str, const char* expected) {
str_parms* str_parms = str_parms_create_str(str);
str_parms_add_str(str_parms, "dude", "woah");
str_parms_add_str(str_parms, "dude", "woah");
str_parms_del(str_parms, "dude");
str_parms_dump(str_parms);
char* out_str = str_parms_to_str(str_parms);
str_parms_destroy(str_parms);
ASSERT_STREQ(expected, out_str) << str;
free(out_str);
}
TEST(str_parms, smoke) {
test_str_parms_str("", "");
test_str_parms_str(";", "");
test_str_parms_str("=", "");
test_str_parms_str("=;", "");
test_str_parms_str("=bar", "");
test_str_parms_str("=bar;", "");
test_str_parms_str("foo=", "foo=");
test_str_parms_str("foo=;", "foo=");
test_str_parms_str("foo=bar", "foo=bar");
test_str_parms_str("foo=bar;", "foo=bar");
test_str_parms_str("foo=bar;baz", "foo=bar;baz=");
test_str_parms_str("foo=bar;baz=", "foo=bar;baz=");
test_str_parms_str("foo=bar;baz=bat", "foo=bar;baz=bat");
test_str_parms_str("foo=bar;baz=bat;", "foo=bar;baz=bat");
test_str_parms_str("foo=bar1;baz=bat;foo=bar2", "foo=bar2;baz=bat");
}
TEST(str_parms, put_ENOMEM) {
// hashmapPut reports errors by setting errno to ENOMEM.
// Test that we're not confused by running in an environment where this is already true.
errno = ENOMEM;
test_str_parms_str("foo=bar;baz=", "foo=bar;baz=");
ASSERT_EQ(ENOMEM, errno);
test_str_parms_str("foo=bar;baz=", "foo=bar;baz=");
}

View file

@ -0,0 +1,295 @@
/*
* Copyright (C) 2016 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.
*/
#include <sys/types.h>
#include <unistd.h>
#include <memory>
#include <string>
#include <android-base/file.h>
#include <android-base/stringprintf.h>
#include <android-base/test_utils.h>
#include <gtest/gtest.h>
#include "../trace-dev.c"
class TraceDevTest : public ::testing::Test {
protected:
void SetUp() override {
lseek(tmp_file_.fd, 0, SEEK_SET);
atrace_marker_fd = tmp_file_.fd;
}
void TearDown() override {
atrace_marker_fd = -1;
}
TemporaryFile tmp_file_;
static std::string MakeName(size_t length) {
std::string name;
for (size_t i = 0; i < length; i++) {
name += '0' + (i % 10);
}
return name;
}
};
TEST_F(TraceDevTest, atrace_begin_body_normal) {
atrace_begin_body("fake_name");
ASSERT_EQ(0, lseek(atrace_marker_fd, 0, SEEK_SET));
std::string actual;
ASSERT_TRUE(android::base::ReadFdToString(atrace_marker_fd, &actual));
std::string expected = android::base::StringPrintf("B|%d|fake_name", getpid());
ASSERT_STREQ(expected.c_str(), actual.c_str());
}
TEST_F(TraceDevTest, atrace_begin_body_exact) {
std::string expected = android::base::StringPrintf("B|%d|", getpid());
std::string name = MakeName(ATRACE_MESSAGE_LENGTH - expected.length() - 1);
atrace_begin_body(name.c_str());
ASSERT_EQ(ATRACE_MESSAGE_LENGTH - 1, lseek(atrace_marker_fd, 0, SEEK_CUR));
ASSERT_EQ(0, lseek(atrace_marker_fd, 0, SEEK_SET));
std::string actual;
ASSERT_TRUE(android::base::ReadFdToString(atrace_marker_fd, &actual));
expected += name;
ASSERT_STREQ(expected.c_str(), actual.c_str());
// Add a single character and verify we get the exact same value as before.
ASSERT_EQ(0, lseek(atrace_marker_fd, 0, SEEK_SET));
name += '*';
atrace_begin_body(name.c_str());
EXPECT_EQ(ATRACE_MESSAGE_LENGTH - 1, lseek(atrace_marker_fd, 0, SEEK_CUR));
ASSERT_EQ(0, lseek(atrace_marker_fd, 0, SEEK_SET));
ASSERT_TRUE(android::base::ReadFdToString(atrace_marker_fd, &actual));
ASSERT_STREQ(expected.c_str(), actual.c_str());
}
TEST_F(TraceDevTest, atrace_begin_body_truncated) {
std::string expected = android::base::StringPrintf("B|%d|", getpid());
std::string name = MakeName(2 * ATRACE_MESSAGE_LENGTH);
atrace_begin_body(name.c_str());
ASSERT_EQ(ATRACE_MESSAGE_LENGTH - 1, lseek(atrace_marker_fd, 0, SEEK_CUR));
ASSERT_EQ(0, lseek(atrace_marker_fd, 0, SEEK_SET));
std::string actual;
ASSERT_TRUE(android::base::ReadFdToString(atrace_marker_fd, &actual));
int expected_len = ATRACE_MESSAGE_LENGTH - expected.length() - 1;
expected += android::base::StringPrintf("%.*s", expected_len, name.c_str());
ASSERT_STREQ(expected.c_str(), actual.c_str());
}
TEST_F(TraceDevTest, atrace_async_begin_body_normal) {
atrace_async_begin_body("fake_name", 12345);
ASSERT_EQ(0, lseek(atrace_marker_fd, 0, SEEK_SET));
std::string actual;
ASSERT_TRUE(android::base::ReadFdToString(atrace_marker_fd, &actual));
std::string expected = android::base::StringPrintf("S|%d|fake_name|12345", getpid());
ASSERT_STREQ(expected.c_str(), actual.c_str());
}
TEST_F(TraceDevTest, atrace_async_begin_body_exact) {
std::string expected = android::base::StringPrintf("S|%d|", getpid());
std::string name = MakeName(ATRACE_MESSAGE_LENGTH - expected.length() - 7);
atrace_async_begin_body(name.c_str(), 12345);
ASSERT_EQ(ATRACE_MESSAGE_LENGTH - 1, lseek(atrace_marker_fd, 0, SEEK_CUR));
ASSERT_EQ(0, lseek(atrace_marker_fd, 0, SEEK_SET));
std::string actual;
ASSERT_TRUE(android::base::ReadFdToString(atrace_marker_fd, &actual));
expected += name + "|12345";
ASSERT_STREQ(expected.c_str(), actual.c_str());
// Add a single character and verify we get the exact same value as before.
ASSERT_EQ(0, lseek(atrace_marker_fd, 0, SEEK_SET));
name += '*';
atrace_async_begin_body(name.c_str(), 12345);
EXPECT_EQ(ATRACE_MESSAGE_LENGTH - 1, lseek(atrace_marker_fd, 0, SEEK_CUR));
ASSERT_EQ(0, lseek(atrace_marker_fd, 0, SEEK_SET));
ASSERT_TRUE(android::base::ReadFdToString(atrace_marker_fd, &actual));
ASSERT_STREQ(expected.c_str(), actual.c_str());
}
TEST_F(TraceDevTest, atrace_async_begin_body_truncated) {
std::string expected = android::base::StringPrintf("S|%d|", getpid());
std::string name = MakeName(2 * ATRACE_MESSAGE_LENGTH);
atrace_async_begin_body(name.c_str(), 12345);
ASSERT_EQ(ATRACE_MESSAGE_LENGTH - 1, lseek(atrace_marker_fd, 0, SEEK_CUR));
ASSERT_EQ(0, lseek(atrace_marker_fd, 0, SEEK_SET));
std::string actual;
ASSERT_TRUE(android::base::ReadFdToString(atrace_marker_fd, &actual));
int expected_len = ATRACE_MESSAGE_LENGTH - expected.length() - 7;
expected += android::base::StringPrintf("%.*s|12345", expected_len, name.c_str());
ASSERT_STREQ(expected.c_str(), actual.c_str());
}
TEST_F(TraceDevTest, atrace_async_end_body_normal) {
atrace_async_end_body("fake_name", 12345);
ASSERT_EQ(0, lseek(atrace_marker_fd, 0, SEEK_SET));
std::string actual;
ASSERT_TRUE(android::base::ReadFdToString(atrace_marker_fd, &actual));
std::string expected = android::base::StringPrintf("F|%d|fake_name|12345", getpid());
ASSERT_STREQ(expected.c_str(), actual.c_str());
}
TEST_F(TraceDevTest, atrace_async_end_body_exact) {
std::string expected = android::base::StringPrintf("F|%d|", getpid());
std::string name = MakeName(ATRACE_MESSAGE_LENGTH - expected.length() - 7);
atrace_async_end_body(name.c_str(), 12345);
ASSERT_EQ(ATRACE_MESSAGE_LENGTH - 1, lseek(atrace_marker_fd, 0, SEEK_CUR));
ASSERT_EQ(0, lseek(atrace_marker_fd, 0, SEEK_SET));
std::string actual;
ASSERT_TRUE(android::base::ReadFdToString(atrace_marker_fd, &actual));
expected += name + "|12345";
ASSERT_STREQ(expected.c_str(), actual.c_str());
// Add a single character and verify we get the exact same value as before.
ASSERT_EQ(0, lseek(atrace_marker_fd, 0, SEEK_SET));
name += '*';
atrace_async_end_body(name.c_str(), 12345);
EXPECT_EQ(ATRACE_MESSAGE_LENGTH - 1, lseek(atrace_marker_fd, 0, SEEK_CUR));
ASSERT_EQ(0, lseek(atrace_marker_fd, 0, SEEK_SET));
ASSERT_TRUE(android::base::ReadFdToString(atrace_marker_fd, &actual));
ASSERT_STREQ(expected.c_str(), actual.c_str());
}
TEST_F(TraceDevTest, atrace_async_end_body_truncated) {
std::string expected = android::base::StringPrintf("F|%d|", getpid());
std::string name = MakeName(2 * ATRACE_MESSAGE_LENGTH);
atrace_async_end_body(name.c_str(), 12345);
ASSERT_EQ(ATRACE_MESSAGE_LENGTH - 1, lseek(atrace_marker_fd, 0, SEEK_CUR));
ASSERT_EQ(0, lseek(atrace_marker_fd, 0, SEEK_SET));
std::string actual;
ASSERT_TRUE(android::base::ReadFdToString(atrace_marker_fd, &actual));
int expected_len = ATRACE_MESSAGE_LENGTH - expected.length() - 7;
expected += android::base::StringPrintf("%.*s|12345", expected_len, name.c_str());
ASSERT_STREQ(expected.c_str(), actual.c_str());
}
TEST_F(TraceDevTest, atrace_int_body_normal) {
atrace_int_body("fake_name", 12345);
ASSERT_EQ(0, lseek(atrace_marker_fd, 0, SEEK_SET));
std::string actual;
ASSERT_TRUE(android::base::ReadFdToString(atrace_marker_fd, &actual));
std::string expected = android::base::StringPrintf("C|%d|fake_name|12345", getpid());
ASSERT_STREQ(expected.c_str(), actual.c_str());
}
TEST_F(TraceDevTest, atrace_int_body_exact) {
std::string expected = android::base::StringPrintf("C|%d|", getpid());
std::string name = MakeName(ATRACE_MESSAGE_LENGTH - expected.length() - 7);
atrace_int_body(name.c_str(), 12345);
ASSERT_EQ(ATRACE_MESSAGE_LENGTH - 1, lseek(atrace_marker_fd, 0, SEEK_CUR));
ASSERT_EQ(0, lseek(atrace_marker_fd, 0, SEEK_SET));
std::string actual;
ASSERT_TRUE(android::base::ReadFdToString(atrace_marker_fd, &actual));
expected += name + "|12345";
ASSERT_STREQ(expected.c_str(), actual.c_str());
// Add a single character and verify we get the exact same value as before.
ASSERT_EQ(0, lseek(atrace_marker_fd, 0, SEEK_SET));
name += '*';
atrace_int_body(name.c_str(), 12345);
EXPECT_EQ(ATRACE_MESSAGE_LENGTH - 1, lseek(atrace_marker_fd, 0, SEEK_CUR));
ASSERT_EQ(0, lseek(atrace_marker_fd, 0, SEEK_SET));
ASSERT_TRUE(android::base::ReadFdToString(atrace_marker_fd, &actual));
ASSERT_STREQ(expected.c_str(), actual.c_str());
}
TEST_F(TraceDevTest, atrace_int_body_truncated) {
std::string expected = android::base::StringPrintf("C|%d|", getpid());
std::string name = MakeName(2 * ATRACE_MESSAGE_LENGTH);
atrace_int_body(name.c_str(), 12345);
ASSERT_EQ(ATRACE_MESSAGE_LENGTH - 1, lseek(atrace_marker_fd, 0, SEEK_CUR));
ASSERT_EQ(0, lseek(atrace_marker_fd, 0, SEEK_SET));
std::string actual;
ASSERT_TRUE(android::base::ReadFdToString(atrace_marker_fd, &actual));
int expected_len = ATRACE_MESSAGE_LENGTH - expected.length() - 7;
expected += android::base::StringPrintf("%.*s|12345", expected_len, name.c_str());
ASSERT_STREQ(expected.c_str(), actual.c_str());
}
TEST_F(TraceDevTest, atrace_int64_body_normal) {
atrace_int64_body("fake_name", 17179869183L);
ASSERT_EQ(0, lseek(atrace_marker_fd, 0, SEEK_SET));
std::string actual;
ASSERT_TRUE(android::base::ReadFdToString(atrace_marker_fd, &actual));
std::string expected = android::base::StringPrintf("C|%d|fake_name|17179869183", getpid());
ASSERT_STREQ(expected.c_str(), actual.c_str());
}
TEST_F(TraceDevTest, atrace_int64_body_exact) {
std::string expected = android::base::StringPrintf("C|%d|", getpid());
std::string name = MakeName(ATRACE_MESSAGE_LENGTH - expected.length() - 13);
atrace_int64_body(name.c_str(), 17179869183L);
ASSERT_EQ(ATRACE_MESSAGE_LENGTH - 1, lseek(atrace_marker_fd, 0, SEEK_CUR));
ASSERT_EQ(0, lseek(atrace_marker_fd, 0, SEEK_SET));
std::string actual;
ASSERT_TRUE(android::base::ReadFdToString(atrace_marker_fd, &actual));
expected += name + "|17179869183";
ASSERT_STREQ(expected.c_str(), actual.c_str());
// Add a single character and verify we get the exact same value as before.
ASSERT_EQ(0, lseek(atrace_marker_fd, 0, SEEK_SET));
name += '*';
atrace_int64_body(name.c_str(), 17179869183L);
EXPECT_EQ(ATRACE_MESSAGE_LENGTH - 1, lseek(atrace_marker_fd, 0, SEEK_CUR));
ASSERT_EQ(0, lseek(atrace_marker_fd, 0, SEEK_SET));
ASSERT_TRUE(android::base::ReadFdToString(atrace_marker_fd, &actual));
ASSERT_STREQ(expected.c_str(), actual.c_str());
}
TEST_F(TraceDevTest, atrace_int64_body_truncated) {
std::string expected = android::base::StringPrintf("C|%d|", getpid());
std::string name = MakeName(2 * ATRACE_MESSAGE_LENGTH);
atrace_int64_body(name.c_str(), 17179869183L);
ASSERT_EQ(ATRACE_MESSAGE_LENGTH - 1, lseek(atrace_marker_fd, 0, SEEK_CUR));
ASSERT_EQ(0, lseek(atrace_marker_fd, 0, SEEK_SET));
std::string actual;
ASSERT_TRUE(android::base::ReadFdToString(atrace_marker_fd, &actual));
int expected_len = ATRACE_MESSAGE_LENGTH - expected.length() - 13;
expected += android::base::StringPrintf("%.*s|17179869183", expected_len, name.c_str());
ASSERT_STREQ(expected.c_str(), actual.c_str());
}