]>
Commit | Line | Data |
---|---|---|
f67539c2 TL |
1 | // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- |
2 | // vim: ts=8 sw=2 smarttab | |
3 | /* | |
4 | * Ceph - scalable distributed file system | |
5 | * | |
6 | * Copyright (C) 2020 Red Hat | |
7 | * | |
8 | * This is free software; you can redistribute it and/or | |
9 | * modify it under the terms of the GNU Lesser General Public | |
10 | * License version 2.1, as published by the Free Software | |
11 | * Foundation. See file COPYING. | |
12 | * | |
13 | */ | |
14 | ||
15 | #include "common/allocate_unique.h" | |
16 | #include <string> | |
17 | #include <vector> | |
18 | #include <gtest/gtest.h> | |
19 | ||
20 | namespace { | |
21 | ||
22 | // allocation events recorded by logging_allocator | |
23 | struct event { | |
24 | size_t size; | |
25 | bool allocated; // true for allocate(), false for deallocate() | |
26 | }; | |
27 | using event_log = std::vector<event>; | |
28 | ||
29 | template <typename T> | |
30 | struct logging_allocator { | |
31 | event_log *const log; | |
32 | ||
33 | using value_type = T; | |
34 | ||
35 | explicit logging_allocator(event_log *log) : log(log) {} | |
36 | logging_allocator(const logging_allocator& other) : log(other.log) {} | |
37 | ||
38 | template <typename U> | |
39 | logging_allocator(const logging_allocator<U>& other) : log(other.log) {} | |
40 | ||
41 | T* allocate(size_t n, const void* hint=0) | |
42 | { | |
43 | auto p = std::allocator<T>{}.allocate(n, hint); | |
44 | log->emplace_back(event{n * sizeof(T), true}); | |
45 | return p; | |
46 | } | |
47 | void deallocate(T* p, size_t n) | |
48 | { | |
49 | std::allocator<T>{}.deallocate(p, n); | |
50 | if (p) { | |
51 | log->emplace_back(event{n * sizeof(T), false}); | |
52 | } | |
53 | } | |
54 | }; | |
55 | ||
56 | } // anonymous namespace | |
57 | ||
58 | namespace ceph { | |
59 | ||
60 | TEST(AllocateUnique, Allocate) | |
61 | { | |
62 | event_log log; | |
63 | auto alloc = logging_allocator<char>{&log}; | |
64 | { | |
65 | auto p = allocate_unique<char>(alloc, 'a'); | |
66 | static_assert(std::is_same_v<decltype(p), | |
67 | std::unique_ptr<char, deallocator<logging_allocator<char>>>>); | |
68 | ASSERT_TRUE(p); | |
69 | ASSERT_EQ(1, log.size()); | |
70 | EXPECT_EQ(1, log.front().size); | |
71 | EXPECT_EQ(true, log.front().allocated); | |
72 | } | |
73 | ASSERT_EQ(2, log.size()); | |
74 | EXPECT_EQ(1, log.back().size); | |
75 | EXPECT_EQ(false, log.back().allocated); | |
76 | } | |
77 | ||
78 | TEST(AllocateUnique, RebindAllocate) | |
79 | { | |
80 | event_log log; | |
81 | auto alloc = logging_allocator<char>{&log}; | |
82 | { | |
83 | auto p = allocate_unique<std::string>(alloc, "a"); | |
84 | static_assert(std::is_same_v<decltype(p), | |
85 | std::unique_ptr<std::string, | |
86 | deallocator<logging_allocator<std::string>>>>); | |
87 | ASSERT_TRUE(p); | |
88 | ASSERT_EQ(1, log.size()); | |
89 | EXPECT_EQ(sizeof(std::string), log.front().size); | |
90 | EXPECT_EQ(true, log.front().allocated); | |
91 | } | |
92 | ASSERT_EQ(2, log.size()); | |
93 | EXPECT_EQ(sizeof(std::string), log.back().size); | |
94 | EXPECT_EQ(false, log.back().allocated); | |
95 | } | |
96 | ||
97 | } // namespace ceph |