File: base-string.cpp

package info (click to toggle)
icinga2 2.15.2-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 20,032 kB
  • sloc: cpp: 97,877; sql: 3,261; cs: 1,636; yacc: 1,584; sh: 1,009; ansic: 890; lex: 420; python: 80; makefile: 62; javascript: 12
file content (146 lines) | stat: -rw-r--r-- 3,780 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
/* Icinga 2 | (c) 2012 Icinga GmbH | GPLv2+ */

#include "base/string.hpp"
#include "base/value.hpp"
#include <vector>
#include <BoostTestTargetConfig.h>

using namespace icinga;

BOOST_AUTO_TEST_SUITE(base_string)

BOOST_AUTO_TEST_CASE(construct)
{
	BOOST_CHECK(String() == "");
	BOOST_CHECK(String(5, 'n') == "nnnnn");
}

BOOST_AUTO_TEST_CASE(equal)
{
	BOOST_CHECK(String("hello") == String("hello"));
	BOOST_CHECK("hello" == String("hello"));
	BOOST_CHECK(String("hello") == String("hello"));

	BOOST_CHECK(String("hello") != String("helloworld"));
	BOOST_CHECK("hello" != String("helloworld"));
	BOOST_CHECK(String("hello") != "helloworld");
}

BOOST_AUTO_TEST_CASE(clear)
{
	String s = "hello";
	s.Clear();
	BOOST_CHECK(s == "");
	BOOST_CHECK(s.IsEmpty());
}

BOOST_AUTO_TEST_CASE(append)
{
	String s;
	s += "he";
	s += String("ll");
	s += 'o';

	BOOST_CHECK(s == "hello");
}

BOOST_AUTO_TEST_CASE(trim)
{
	String s1 = "hello";
	BOOST_CHECK(s1.Trim() == "hello");

	String s2 = "  hello";
	BOOST_CHECK(s2.Trim() == "hello");

	String s3 = "hello ";
	BOOST_CHECK(s3.Trim() == "hello");

	String s4 = " hello ";
	BOOST_CHECK(s4.Trim() == "hello");
}

BOOST_AUTO_TEST_CASE(contains)
{
	String s1 = "hello world";
	String s2 = "hello";
	BOOST_CHECK(s1.Contains(s2));

	String s3 = "  hello world  ";
	String s4 = "  hello";
	BOOST_CHECK(s3.Contains(s4));

	String s5 = "  hello world  ";
	String s6 = "world  ";
	BOOST_CHECK(s5.Contains(s6));
}

BOOST_AUTO_TEST_CASE(replace)
{
	String s = "hello";

	s.Replace(0, 2, "x");
	BOOST_CHECK(s == "xllo");
}

BOOST_AUTO_TEST_CASE(index)
{
	String s = "hello";
	BOOST_CHECK(s[0] == 'h');

	s[0] = 'x';
	BOOST_CHECK(s == "xello");

	for (char& ch : s) {
		ch = 'y';
	}
	BOOST_CHECK(s == "yyyyy");
}

BOOST_AUTO_TEST_CASE(find)
{
	String s = "hello";
	BOOST_CHECK(s.Find("ll") == 2);
	BOOST_CHECK(s.FindFirstOf("xl") == 2);
}

// Check that if a std::vector<icinga::String> is grown beyond its capacity (i.e. it has to reallocate the memory),
// it uses the move constructor of icinga::String (i.e. the underlying string storage stays the same).
BOOST_AUTO_TEST_CASE(vector_move)
{
	std::vector<String> vec {
		// std::string (which is internally used by icinga::String) has an optimization that small strings can be
		// allocated inside it instead of in a separate heap allocation. In that case, the small string would still be
		// copied even by the move constructor. Using sizeof() ensures that the string is long enough so that it must
		// be allocated separately and can be used to test for the desired move to happen.
		std::string(sizeof(String) + 1, 'A'),
	};

	void *oldAddr = vec[0].GetData().data();
	// Sanity check that the data buffer is actually allocated outside the icinga::String instance.
	BOOST_CHECK(!(vec.data() <= oldAddr && oldAddr < vec.data() + vec.size()));

	// Force the vector to grow.
	vec.reserve(vec.capacity() + 1);

	// If the string was moved, the location of its underlying data buffer should not have changed.
	void *newAddr = vec[0].GetData().data();
	BOOST_CHECK_EQUAL(oldAddr, newAddr);
}

// Test that the move constructor of icinga::String actually moves the underlying std::string out of a Value instance.
// The constructor overload is only available on non-Windows platforms though, so we need to skip the test on Windows.
BOOST_AUTO_TEST_CASE(move_string_out_of_Value_type)
{
#ifndef _MSC_VER
	Value value("Icinga 2");
	String other = value.Get<String>(); // We didn't request a move, so this should just copy the string.
	BOOST_CHECK_EQUAL("Icinga 2", value.Get<String>());
	BOOST_CHECK_EQUAL("Icinga 2", other);

	String newStr = std::move(value);
	BOOST_CHECK_EQUAL("", value.Get<String>());
	BOOST_CHECK_EQUAL(newStr, "Icinga 2");
#endif /* _MSC_VER */
}

BOOST_AUTO_TEST_SUITE_END()