1d89ec533Spatrick //===-- common_test.cpp -----------------------------------------*- C++ -*-===//
2d89ec533Spatrick //
3d89ec533Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4d89ec533Spatrick // See https://llvm.org/LICENSE.txt for license information.
5d89ec533Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6d89ec533Spatrick //
7d89ec533Spatrick //===----------------------------------------------------------------------===//
8d89ec533Spatrick
9d89ec533Spatrick #include "internal_defs.h"
10d89ec533Spatrick #include "tests/scudo_unit_test.h"
11d89ec533Spatrick
12d89ec533Spatrick #include "common.h"
13d89ec533Spatrick #include <algorithm>
14d89ec533Spatrick #include <fstream>
15d89ec533Spatrick
16d89ec533Spatrick namespace scudo {
17d89ec533Spatrick
getResidentMemorySize()18d89ec533Spatrick static uptr getResidentMemorySize() {
19d89ec533Spatrick if (!SCUDO_LINUX)
20d89ec533Spatrick UNREACHABLE("Not implemented!");
21d89ec533Spatrick uptr Size;
22d89ec533Spatrick uptr Resident;
23d89ec533Spatrick std::ifstream IFS("/proc/self/statm");
24d89ec533Spatrick IFS >> Size;
25d89ec533Spatrick IFS >> Resident;
26d89ec533Spatrick return Resident * getPageSizeCached();
27d89ec533Spatrick }
28d89ec533Spatrick
29d89ec533Spatrick // Fuchsia needs getResidentMemorySize implementation.
TEST(ScudoCommonTest,SKIP_ON_FUCHSIA (ResidentMemorySize))30d89ec533Spatrick TEST(ScudoCommonTest, SKIP_ON_FUCHSIA(ResidentMemorySize)) {
31d89ec533Spatrick uptr OnStart = getResidentMemorySize();
32d89ec533Spatrick EXPECT_GT(OnStart, 0UL);
33d89ec533Spatrick
34d89ec533Spatrick const uptr Size = 1ull << 30;
35d89ec533Spatrick const uptr Threshold = Size >> 3;
36d89ec533Spatrick
37d89ec533Spatrick MapPlatformData Data = {};
38d89ec533Spatrick void *P = map(nullptr, Size, "ResidentMemorySize", 0, &Data);
39d89ec533Spatrick ASSERT_NE(nullptr, P);
40d89ec533Spatrick EXPECT_LT(getResidentMemorySize(), OnStart + Threshold);
41d89ec533Spatrick
42d89ec533Spatrick memset(P, 1, Size);
43d89ec533Spatrick EXPECT_GT(getResidentMemorySize(), OnStart + Size - Threshold);
44d89ec533Spatrick
45d89ec533Spatrick releasePagesToOS((uptr)P, 0, Size, &Data);
46d89ec533Spatrick EXPECT_LT(getResidentMemorySize(), OnStart + Threshold);
47d89ec533Spatrick
48d89ec533Spatrick memset(P, 1, Size);
49d89ec533Spatrick EXPECT_GT(getResidentMemorySize(), OnStart + Size - Threshold);
50d89ec533Spatrick
51d89ec533Spatrick unmap(P, Size, 0, &Data);
52d89ec533Spatrick }
53d89ec533Spatrick
TEST(ScudoCommonTest,Zeros)54d89ec533Spatrick TEST(ScudoCommonTest, Zeros) {
55d89ec533Spatrick const uptr Size = 1ull << 20;
56d89ec533Spatrick
57d89ec533Spatrick MapPlatformData Data = {};
58d89ec533Spatrick uptr *P = reinterpret_cast<uptr *>(map(nullptr, Size, "Zeros", 0, &Data));
59d89ec533Spatrick const ptrdiff_t N = Size / sizeof(*P);
60d89ec533Spatrick ASSERT_NE(nullptr, P);
61d89ec533Spatrick EXPECT_EQ(std::count(P, P + N, 0), N);
62d89ec533Spatrick
63d89ec533Spatrick memset(P, 1, Size);
64d89ec533Spatrick EXPECT_EQ(std::count(P, P + N, 0), 0);
65d89ec533Spatrick
66d89ec533Spatrick releasePagesToOS((uptr)P, 0, Size, &Data);
67d89ec533Spatrick EXPECT_EQ(std::count(P, P + N, 0), N);
68d89ec533Spatrick
69d89ec533Spatrick unmap(P, Size, 0, &Data);
70d89ec533Spatrick }
71d89ec533Spatrick
72*810390e3Srobert #if SCUDO_LINUX && !defined(__powerpc__)
73*810390e3Srobert // This test fails intermediately on PPC, which is why this test is disabled
74*810390e3Srobert // for now on this platform.
TEST(ScudoCommonTest,GetRssFromBuffer)75*810390e3Srobert TEST(ScudoCommonTest, GetRssFromBuffer) {
76*810390e3Srobert constexpr int64_t AllocSize = 10000000;
77*810390e3Srobert constexpr int64_t Error = 3000000;
78*810390e3Srobert constexpr size_t Runs = 10;
79*810390e3Srobert
80*810390e3Srobert int64_t Rss = scudo::GetRSS();
81*810390e3Srobert EXPECT_GT(Rss, 0);
82*810390e3Srobert
83*810390e3Srobert std::vector<std::unique_ptr<char[]>> Allocs(Runs);
84*810390e3Srobert for (auto &Alloc : Allocs) {
85*810390e3Srobert Alloc.reset(new char[AllocSize]());
86*810390e3Srobert int64_t Prev = Rss;
87*810390e3Srobert Rss = scudo::GetRSS();
88*810390e3Srobert EXPECT_LE(std::abs(Rss - AllocSize - Prev), Error);
89*810390e3Srobert }
90*810390e3Srobert }
91*810390e3Srobert #endif // SCUDO_LINUX
92*810390e3Srobert
93d89ec533Spatrick } // namespace scudo
94