15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2003, Google Inc.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// All rights reserved.
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Redistribution and use in source and binary forms, with or without
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// modification, are permitted provided that the following conditions are
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// met:
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//     * Redistributions of source code must retain the above copyright
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// notice, this list of conditions and the following disclaimer.
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//     * Redistributions in binary form must reproduce the above
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// copyright notice, this list of conditions and the following disclaimer
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// in the documentation and/or other materials provided with the
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// distribution.
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//     * Neither the name of Google Inc. nor the names of its
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// contributors may be used to endorse or promote products derived from
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// this software without specific prior written permission.
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ---
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Author: Sanjay Ghemawat
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "config_for_unittests.h"
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <stdio.h>
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <stdlib.h>
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined HAVE_STDINT_H
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <stdint.h>             // to get intptr_t
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined HAVE_INTTYPES_H
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <inttypes.h>           // another place intptr_t might be defined
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sys/types.h>
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <vector>
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "pagemap.h"
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using std::vector;
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void Permute(vector<intptr_t>* elements) {
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (elements->empty())
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const size_t num_elements = elements->size();
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = num_elements - 1; i > 0; --i) {
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const size_t newpos = rand() % (i + 1);
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const intptr_t tmp = (*elements)[i];   // swap
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    (*elements)[i] = (*elements)[newpos];
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    (*elements)[newpos] = tmp;
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Note: we leak memory every time a map is constructed, so do not
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// create too many maps.
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Test specified map type
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <class Type>
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TestMap(int limit, bool limit_is_below_the_overflow_boundary) {
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RAW_LOG(INFO, "Running test with %d iterations...\n", limit);
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { // Test sequential ensure/assignment
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Type map(malloc);
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (intptr_t i = 0; i < static_cast<intptr_t>(limit); i++) {
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      map.Ensure(i, 1);
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      map.set(i, (void*)(i+1));
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CHECK_EQ(map.get(i), (void*)(i+1));
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (intptr_t i = 0; i < static_cast<intptr_t>(limit); i++) {
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CHECK_EQ(map.get(i), (void*)(i+1));
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { // Test bulk Ensure
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Type map(malloc);
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    map.Ensure(0, limit);
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (intptr_t i = 0; i < static_cast<intptr_t>(limit); i++) {
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      map.set(i, (void*)(i+1));
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CHECK_EQ(map.get(i), (void*)(i+1));
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (intptr_t i = 0; i < static_cast<intptr_t>(limit); i++) {
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CHECK_EQ(map.get(i), (void*)(i+1));
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Test that we correctly notice overflow
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Type map(malloc);
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CHECK_EQ(map.Ensure(limit, limit+1), limit_is_below_the_overflow_boundary);
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { // Test randomized accesses
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    srand(301);   // srand isn't great, but it's portable
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    vector<intptr_t> elements;
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (intptr_t i = 0; i < static_cast<intptr_t>(limit); i++) elements.push_back(i);
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Permute(&elements);
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Type map(malloc);
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (intptr_t i = 0; i < static_cast<intptr_t>(limit); i++) {
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      map.Ensure(elements[i], 1);
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      map.set(elements[i], (void*)(elements[i]+1));
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CHECK_EQ(map.get(elements[i]), (void*)(elements[i]+1));
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (intptr_t i = 0; i < static_cast<intptr_t>(limit); i++) {
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CHECK_EQ(map.get(i), (void*)(i+1));
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// REQUIRES: BITS==10, i.e., valid range is [0,1023].
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Representations for different types will end up being:
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//    PageMap1: array[1024]
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//    PageMap2: array[32][32]
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//    PageMap3: array[16][16][4]
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <class Type>
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TestNext(const char* name) {
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RAW_LOG(ERROR, "Running NextTest %s\n", name);
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Type map(malloc);
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char a, b, c, d, e;
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // When map is empty
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK(map.Next(0) == NULL);
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK(map.Next(5) == NULL);
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK(map.Next(1<<30) == NULL);
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Add a single value
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  map.Ensure(40, 1);
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  map.set(40, &a);
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK(map.Next(0) == &a);
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK(map.Next(39) == &a);
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK(map.Next(40) == &a);
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK(map.Next(41) == NULL);
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK(map.Next(1<<30) == NULL);
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Add a few values
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  map.Ensure(41, 1);
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  map.Ensure(100, 3);
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  map.set(41, &b);
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  map.set(100, &c);
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  map.set(101, &d);
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  map.set(102, &e);
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK(map.Next(0) == &a);
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK(map.Next(39) == &a);
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK(map.Next(40) == &a);
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK(map.Next(41) == &b);
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK(map.Next(42) == &c);
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK(map.Next(63) == &c);
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK(map.Next(64) == &c);
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK(map.Next(65) == &c);
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK(map.Next(99) == &c);
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK(map.Next(100) == &c);
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK(map.Next(101) == &d);
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK(map.Next(102) == &e);
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK(map.Next(103) == NULL);
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int main(int argc, char** argv) {
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestMap< TCMalloc_PageMap1<10> > (100, true);
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestMap< TCMalloc_PageMap1<10> > (1 << 10, false);
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestMap< TCMalloc_PageMap2<20> > (100, true);
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestMap< TCMalloc_PageMap2<20> > (1 << 20, false);
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestMap< TCMalloc_PageMap3<20> > (100, true);
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestMap< TCMalloc_PageMap3<20> > (1 << 20, false);
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestNext< TCMalloc_PageMap1<10> >("PageMap1");
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestNext< TCMalloc_PageMap2<10> >("PageMap2");
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestNext< TCMalloc_PageMap3<10> >("PageMap3");
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printf("PASS\n");
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return 0;
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
178