blob: 88d46e75f93a8ba2274d8844c3560caebb8bd984 [file] [log] [blame]
Austin Schuh745610d2015-09-06 18:19:50 -07001// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
2// Copyright (c) 2003, Google Inc.
3// All rights reserved.
4//
5// Redistribution and use in source and binary forms, with or without
6// modification, are permitted provided that the following conditions are
7// met:
8//
9// * Redistributions of source code must retain the above copyright
10// notice, this list of conditions and the following disclaimer.
11// * Redistributions in binary form must reproduce the above
12// copyright notice, this list of conditions and the following disclaimer
13// in the documentation and/or other materials provided with the
14// distribution.
15// * Neither the name of Google Inc. nor the names of its
16// contributors may be used to endorse or promote products derived from
17// this software without specific prior written permission.
18//
19// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
31// ---
32// Author: Sanjay Ghemawat
33
34#include "config_for_unittests.h"
35#include <stdio.h>
36#include <stdlib.h>
37#if defined HAVE_STDINT_H
38#include <stdint.h> // to get intptr_t
39#elif defined HAVE_INTTYPES_H
40#include <inttypes.h> // another place intptr_t might be defined
41#endif
42#include <sys/types.h>
43#include <vector>
44#include "base/logging.h"
45#include "pagemap.h"
46
47using std::vector;
48
49static void Permute(vector<intptr_t>* elements) {
50 if (elements->empty())
51 return;
52 const size_t num_elements = elements->size();
53 for (size_t i = num_elements - 1; i > 0; --i) {
54 const size_t newpos = rand() % (i + 1);
55 const intptr_t tmp = (*elements)[i]; // swap
56 (*elements)[i] = (*elements)[newpos];
57 (*elements)[newpos] = tmp;
58 }
59}
60
61// Note: we leak memory every time a map is constructed, so do not
62// create too many maps.
63
64// Test specified map type
65template <class Type>
66void TestMap(int limit, bool limit_is_below_the_overflow_boundary) {
67 RAW_LOG(INFO, "Running test with %d iterations...\n", limit);
68
69 { // Test sequential ensure/assignment
70 Type map(malloc);
71 for (intptr_t i = 0; i < static_cast<intptr_t>(limit); i++) {
72 map.Ensure(i, 1);
73 map.set(i, (void*)(i+1));
74 CHECK_EQ(map.get(i), (void*)(i+1));
75 }
76 for (intptr_t i = 0; i < static_cast<intptr_t>(limit); i++) {
77 CHECK_EQ(map.get(i), (void*)(i+1));
78 }
79 }
80
81 { // Test bulk Ensure
82 Type map(malloc);
83 map.Ensure(0, limit);
84 for (intptr_t i = 0; i < static_cast<intptr_t>(limit); i++) {
85 map.set(i, (void*)(i+1));
86 CHECK_EQ(map.get(i), (void*)(i+1));
87 }
88 for (intptr_t i = 0; i < static_cast<intptr_t>(limit); i++) {
89 CHECK_EQ(map.get(i), (void*)(i+1));
90 }
91 }
92
93 // Test that we correctly notice overflow
94 {
95 Type map(malloc);
96 CHECK_EQ(map.Ensure(limit, limit+1), limit_is_below_the_overflow_boundary);
97 }
98
99 { // Test randomized accesses
100 srand(301); // srand isn't great, but it's portable
101 vector<intptr_t> elements;
102 for (intptr_t i = 0; i < static_cast<intptr_t>(limit); i++) elements.push_back(i);
103 Permute(&elements);
104
105 Type map(malloc);
106 for (intptr_t i = 0; i < static_cast<intptr_t>(limit); i++) {
107 map.Ensure(elements[i], 1);
108 map.set(elements[i], (void*)(elements[i]+1));
109 CHECK_EQ(map.get(elements[i]), (void*)(elements[i]+1));
110 }
111 for (intptr_t i = 0; i < static_cast<intptr_t>(limit); i++) {
112 CHECK_EQ(map.get(i), (void*)(i+1));
113 }
114 }
115}
116
117// REQUIRES: BITS==10, i.e., valid range is [0,1023].
118// Representations for different types will end up being:
119// PageMap1: array[1024]
120// PageMap2: array[32][32]
121// PageMap3: array[16][16][4]
122template <class Type>
123void TestNext(const char* name) {
124 RAW_LOG(ERROR, "Running NextTest %s\n", name);
125 Type map(malloc);
126 char a, b, c, d, e;
127
128 // When map is empty
129 CHECK(map.Next(0) == NULL);
130 CHECK(map.Next(5) == NULL);
131 CHECK(map.Next(1<<30) == NULL);
132
133 // Add a single value
134 map.Ensure(40, 1);
135 map.set(40, &a);
136 CHECK(map.Next(0) == &a);
137 CHECK(map.Next(39) == &a);
138 CHECK(map.Next(40) == &a);
139 CHECK(map.Next(41) == NULL);
140 CHECK(map.Next(1<<30) == NULL);
141
142 // Add a few values
143 map.Ensure(41, 1);
144 map.Ensure(100, 3);
145 map.set(41, &b);
146 map.set(100, &c);
147 map.set(101, &d);
148 map.set(102, &e);
149 CHECK(map.Next(0) == &a);
150 CHECK(map.Next(39) == &a);
151 CHECK(map.Next(40) == &a);
152 CHECK(map.Next(41) == &b);
153 CHECK(map.Next(42) == &c);
154 CHECK(map.Next(63) == &c);
155 CHECK(map.Next(64) == &c);
156 CHECK(map.Next(65) == &c);
157 CHECK(map.Next(99) == &c);
158 CHECK(map.Next(100) == &c);
159 CHECK(map.Next(101) == &d);
160 CHECK(map.Next(102) == &e);
161 CHECK(map.Next(103) == NULL);
162}
163
164int main(int argc, char** argv) {
165 TestMap< TCMalloc_PageMap1<10> > (100, true);
166 TestMap< TCMalloc_PageMap1<10> > (1 << 10, false);
167 TestMap< TCMalloc_PageMap2<20> > (100, true);
168 TestMap< TCMalloc_PageMap2<20> > (1 << 20, false);
169 TestMap< TCMalloc_PageMap3<20> > (100, true);
170 TestMap< TCMalloc_PageMap3<20> > (1 << 20, false);
171
172 TestNext< TCMalloc_PageMap1<10> >("PageMap1");
173 TestNext< TCMalloc_PageMap2<10> >("PageMap2");
174 TestNext< TCMalloc_PageMap3<10> >("PageMap3");
175
176 printf("PASS\n");
177 return 0;
178}