1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include "nsASCIIMask.h"
10 #include "nsString.h"
11 #include "nsStringBuffer.h"
12 #include "nsReadableUtils.h"
13 #include "nsCRTGlue.h"
14 #include "mozilla/RefPtr.h"
15 #include "mozilla/Unused.h"
16 #include "gtest/gtest.h"
17
18 namespace TestMoveString {
19
20 #define NEW_VAL "**new value**"
21 #define OLD_VAL "old value"
22
23 typedef mozilla::detail::StringDataFlags Df;
24
SetAsOwned(nsACString & aStr,const char * aValue)25 static void SetAsOwned(nsACString& aStr, const char* aValue) {
26 size_t len = strlen(aValue);
27 char* data = new char[len + 1];
28 memcpy(data, aValue, len + 1);
29 aStr.Adopt(data, len);
30 EXPECT_EQ(aStr.GetDataFlags(), Df::OWNED | Df::TERMINATED);
31 EXPECT_STREQ(aStr.BeginReading(), aValue);
32 }
33
ExpectTruncated(const nsACString & aStr)34 static void ExpectTruncated(const nsACString& aStr) {
35 EXPECT_EQ(aStr.Length(), uint32_t(0));
36 EXPECT_STREQ(aStr.BeginReading(), "");
37 EXPECT_EQ(aStr.GetDataFlags(), Df::TERMINATED);
38 }
39
ExpectNew(const nsACString & aStr)40 static void ExpectNew(const nsACString& aStr) {
41 EXPECT_EQ(aStr.Length(), strlen(NEW_VAL));
42 EXPECT_TRUE(aStr.EqualsASCII(NEW_VAL));
43 }
44
TEST(MoveString,SharedIntoOwned)45 TEST(MoveString, SharedIntoOwned)
46 {
47 nsCString out;
48 SetAsOwned(out, OLD_VAL);
49 EXPECT_EQ(out.GetDataFlags(), Df::OWNED | Df::TERMINATED);
50
51 nsCString in;
52 in.Assign(NEW_VAL);
53 EXPECT_EQ(in.GetDataFlags(), Df::REFCOUNTED | Df::TERMINATED);
54 const char* data = in.get();
55
56 out.Assign(std::move(in));
57 ExpectTruncated(in);
58 ExpectNew(out);
59
60 EXPECT_EQ(out.GetDataFlags(), Df::REFCOUNTED | Df::TERMINATED);
61 EXPECT_EQ(out.get(), data);
62 }
63
TEST(MoveString,OwnedIntoOwned)64 TEST(MoveString, OwnedIntoOwned)
65 {
66 nsCString out;
67 SetAsOwned(out, OLD_VAL);
68 EXPECT_EQ(out.GetDataFlags(), Df::OWNED | Df::TERMINATED);
69
70 nsCString in;
71 SetAsOwned(in, NEW_VAL);
72 EXPECT_EQ(in.GetDataFlags(), Df::OWNED | Df::TERMINATED);
73 const char* data = in.get();
74
75 out.Assign(std::move(in));
76 ExpectTruncated(in);
77 ExpectNew(out);
78
79 EXPECT_EQ(out.GetDataFlags(), Df::OWNED | Df::TERMINATED);
80 EXPECT_EQ(out.get(), data);
81 }
82
TEST(MoveString,LiteralIntoOwned)83 TEST(MoveString, LiteralIntoOwned)
84 {
85 nsCString out;
86 SetAsOwned(out, OLD_VAL);
87 EXPECT_EQ(out.GetDataFlags(), Df::OWNED | Df::TERMINATED);
88
89 nsCString in;
90 in.AssignLiteral(NEW_VAL);
91 EXPECT_EQ(in.GetDataFlags(), Df::LITERAL | Df::TERMINATED);
92 const char* data = in.get();
93
94 out.Assign(std::move(in));
95 ExpectTruncated(in);
96 ExpectNew(out);
97
98 EXPECT_EQ(out.GetDataFlags(), Df::LITERAL | Df::TERMINATED);
99 EXPECT_EQ(out.get(), data);
100 }
101
TEST(MoveString,AutoIntoOwned)102 TEST(MoveString, AutoIntoOwned)
103 {
104 nsCString out;
105 SetAsOwned(out, OLD_VAL);
106 EXPECT_EQ(out.GetDataFlags(), Df::OWNED | Df::TERMINATED);
107
108 nsAutoCString in;
109 in.Assign(NEW_VAL);
110 EXPECT_EQ(in.GetDataFlags(), Df::INLINE | Df::TERMINATED);
111 const char* data = in.get();
112
113 out.Assign(std::move(in));
114 ExpectTruncated(in);
115 ExpectNew(out);
116
117 EXPECT_EQ(out.GetDataFlags(), Df::REFCOUNTED | Df::TERMINATED);
118 EXPECT_NE(out.get(), data);
119 }
120
TEST(MoveString,DepIntoOwned)121 TEST(MoveString, DepIntoOwned)
122 {
123 nsCString out;
124 SetAsOwned(out, OLD_VAL);
125 EXPECT_EQ(out.GetDataFlags(), Df::OWNED | Df::TERMINATED);
126
127 nsDependentCSubstring in(NEW_VAL "garbage after", strlen(NEW_VAL));
128 EXPECT_EQ(in.GetDataFlags(), Df(0));
129
130 out.Assign(std::move(in));
131 ExpectTruncated(in);
132 ExpectNew(out);
133
134 EXPECT_EQ(out.GetDataFlags(), Df::REFCOUNTED | Df::TERMINATED);
135 }
136
TEST(MoveString,VoidIntoOwned)137 TEST(MoveString, VoidIntoOwned)
138 {
139 nsCString out;
140 SetAsOwned(out, OLD_VAL);
141 EXPECT_EQ(out.GetDataFlags(), Df::OWNED | Df::TERMINATED);
142
143 nsCString in = VoidCString();
144 EXPECT_EQ(in.GetDataFlags(), Df::VOIDED | Df::TERMINATED);
145
146 out.Assign(std::move(in));
147 ExpectTruncated(in);
148
149 EXPECT_EQ(out.Length(), 0u);
150 EXPECT_STREQ(out.get(), "");
151 EXPECT_EQ(out.GetDataFlags(), Df::VOIDED | Df::TERMINATED);
152 }
153
TEST(MoveString,SharedIntoAuto)154 TEST(MoveString, SharedIntoAuto)
155 {
156 nsAutoCString out;
157 out.Assign(OLD_VAL);
158 EXPECT_EQ(out.GetDataFlags(), Df::INLINE | Df::TERMINATED);
159
160 nsCString in;
161 in.Assign(NEW_VAL);
162 EXPECT_EQ(in.GetDataFlags(), Df::REFCOUNTED | Df::TERMINATED);
163 const char* data = in.get();
164
165 out.Assign(std::move(in));
166 ExpectTruncated(in);
167 ExpectNew(out);
168
169 EXPECT_EQ(out.GetDataFlags(), Df::REFCOUNTED | Df::TERMINATED);
170 EXPECT_EQ(out.get(), data);
171 }
172
TEST(MoveString,OwnedIntoAuto)173 TEST(MoveString, OwnedIntoAuto)
174 {
175 nsAutoCString out;
176 out.Assign(OLD_VAL);
177 EXPECT_EQ(out.GetDataFlags(), Df::INLINE | Df::TERMINATED);
178
179 nsCString in;
180 SetAsOwned(in, NEW_VAL);
181 EXPECT_EQ(in.GetDataFlags(), Df::OWNED | Df::TERMINATED);
182 const char* data = in.get();
183
184 out.Assign(std::move(in));
185 ExpectTruncated(in);
186 ExpectNew(out);
187
188 EXPECT_EQ(out.GetDataFlags(), Df::OWNED | Df::TERMINATED);
189 EXPECT_EQ(out.get(), data);
190 }
191
TEST(MoveString,LiteralIntoAuto)192 TEST(MoveString, LiteralIntoAuto)
193 {
194 nsAutoCString out;
195 out.Assign(OLD_VAL);
196 EXPECT_EQ(out.GetDataFlags(), Df::INLINE | Df::TERMINATED);
197
198 nsCString in;
199 in.AssignLiteral(NEW_VAL);
200 EXPECT_EQ(in.GetDataFlags(), Df::LITERAL | Df::TERMINATED);
201 const char* data = in.get();
202
203 out.Assign(std::move(in));
204 ExpectTruncated(in);
205 ExpectNew(out);
206
207 EXPECT_EQ(out.GetDataFlags(), Df::LITERAL | Df::TERMINATED);
208 EXPECT_EQ(out.get(), data);
209 }
210
TEST(MoveString,AutoIntoAuto)211 TEST(MoveString, AutoIntoAuto)
212 {
213 nsAutoCString out;
214 out.Assign(OLD_VAL);
215 EXPECT_EQ(out.GetDataFlags(), Df::INLINE | Df::TERMINATED);
216
217 nsAutoCString in;
218 in.Assign(NEW_VAL);
219 EXPECT_EQ(in.GetDataFlags(), Df::INLINE | Df::TERMINATED);
220 const char* data = in.get();
221
222 out.Assign(std::move(in));
223 ExpectTruncated(in);
224 ExpectNew(out);
225
226 EXPECT_EQ(out.GetDataFlags(), Df::INLINE | Df::TERMINATED);
227 EXPECT_NE(out.get(), data);
228 }
229
TEST(MoveString,DepIntoAuto)230 TEST(MoveString, DepIntoAuto)
231 {
232 nsAutoCString out;
233 out.Assign(OLD_VAL);
234 EXPECT_EQ(out.GetDataFlags(), Df::INLINE | Df::TERMINATED);
235
236 nsDependentCSubstring in(NEW_VAL "garbage after", strlen(NEW_VAL));
237 EXPECT_EQ(in.GetDataFlags(), Df(0));
238
239 out.Assign(std::move(in));
240 ExpectTruncated(in);
241 ExpectNew(out);
242
243 EXPECT_EQ(out.GetDataFlags(), Df::INLINE | Df::TERMINATED);
244 }
245
TEST(MoveString,VoidIntoAuto)246 TEST(MoveString, VoidIntoAuto)
247 {
248 nsAutoCString out;
249 out.Assign(OLD_VAL);
250 EXPECT_EQ(out.GetDataFlags(), Df::INLINE | Df::TERMINATED);
251
252 nsCString in = VoidCString();
253 EXPECT_EQ(in.GetDataFlags(), Df::VOIDED | Df::TERMINATED);
254
255 out.Assign(std::move(in));
256 ExpectTruncated(in);
257
258 EXPECT_EQ(out.Length(), 0u);
259 EXPECT_STREQ(out.get(), "");
260 EXPECT_EQ(out.GetDataFlags(), Df::VOIDED | Df::TERMINATED);
261 }
262
263 #undef NEW_VAL
264 #undef OLD_VAL
265
266 } // namespace TestMoveString
267