/src/mozilla-central/xpcom/tests/gtest/TestAtoms.cpp
Line | Count | Source (jump to first uncovered line) |
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 "mozilla/ArrayUtils.h" |
8 | | |
9 | | #include "nsAtom.h" |
10 | | #include "nsString.h" |
11 | | #include "UTFStrings.h" |
12 | | #include "nsIServiceManager.h" |
13 | | #include "nsThreadUtils.h" |
14 | | |
15 | | #include "gtest/gtest.h" |
16 | | |
17 | | using namespace mozilla; |
18 | | |
19 | | int32_t NS_GetUnusedAtomCount(void); |
20 | | |
21 | | namespace TestAtoms { |
22 | | |
23 | | TEST(Atoms, Basic) |
24 | 0 | { |
25 | 0 | for (unsigned int i = 0; i < ArrayLength(ValidStrings); ++i) { |
26 | 0 | nsDependentString str16(ValidStrings[i].m16); |
27 | 0 | nsDependentCString str8(ValidStrings[i].m8); |
28 | 0 |
|
29 | 0 | RefPtr<nsAtom> atom = NS_Atomize(str16); |
30 | 0 |
|
31 | 0 | EXPECT_TRUE(atom->Equals(str16)); |
32 | 0 |
|
33 | 0 | nsString tmp16; |
34 | 0 | nsCString tmp8; |
35 | 0 | atom->ToString(tmp16); |
36 | 0 | atom->ToUTF8String(tmp8); |
37 | 0 | EXPECT_TRUE(str16.Equals(tmp16)); |
38 | 0 | EXPECT_TRUE(str8.Equals(tmp8)); |
39 | 0 |
|
40 | 0 | EXPECT_TRUE(nsDependentString(atom->GetUTF16String()).Equals(str16)); |
41 | 0 |
|
42 | 0 | EXPECT_TRUE(nsAtomString(atom).Equals(str16)); |
43 | 0 | EXPECT_TRUE(nsDependentAtomString(atom).Equals(str16)); |
44 | 0 | EXPECT_TRUE(nsAtomCString(atom).Equals(str8)); |
45 | 0 | } |
46 | 0 | } |
47 | | |
48 | | TEST(Atoms, 16vs8) |
49 | 0 | { |
50 | 0 | for (unsigned int i = 0; i < ArrayLength(ValidStrings); ++i) { |
51 | 0 | RefPtr<nsAtom> atom16 = NS_Atomize(ValidStrings[i].m16); |
52 | 0 | RefPtr<nsAtom> atom8 = NS_Atomize(ValidStrings[i].m8); |
53 | 0 | EXPECT_EQ(atom16, atom8); |
54 | 0 | } |
55 | 0 | } |
56 | | |
57 | | TEST(Atoms, Null) |
58 | 0 | { |
59 | 0 | nsAutoString str(NS_LITERAL_STRING("string with a \0 char")); |
60 | 0 | nsDependentString strCut(str.get()); |
61 | 0 |
|
62 | 0 | EXPECT_FALSE(str.Equals(strCut)); |
63 | 0 |
|
64 | 0 | RefPtr<nsAtom> atomCut = NS_Atomize(strCut); |
65 | 0 | RefPtr<nsAtom> atom = NS_Atomize(str); |
66 | 0 |
|
67 | 0 | EXPECT_EQ(atom->GetLength(), str.Length()); |
68 | 0 | EXPECT_TRUE(atom->Equals(str)); |
69 | 0 | EXPECT_NE(atom, atomCut); |
70 | 0 | EXPECT_TRUE(atomCut->Equals(strCut)); |
71 | 0 | } |
72 | | |
73 | | TEST(Atoms, Invalid) |
74 | 0 | { |
75 | 0 | for (unsigned int i = 0; i < ArrayLength(Invalid16Strings); ++i) { |
76 | 0 | nsrefcnt count = NS_GetNumberOfAtoms(); |
77 | 0 |
|
78 | 0 | { |
79 | 0 | RefPtr<nsAtom> atom16 = NS_Atomize(Invalid16Strings[i].m16); |
80 | 0 | EXPECT_TRUE(atom16->Equals(nsDependentString(Invalid16Strings[i].m16))); |
81 | 0 | } |
82 | 0 |
|
83 | 0 | EXPECT_EQ(count, NS_GetNumberOfAtoms()); |
84 | 0 | } |
85 | 0 | #ifndef DEBUG |
86 | 0 | // Don't run this test in debug builds as that intentionally asserts. |
87 | 0 | for (unsigned int i = 0; i < ArrayLength(Invalid8Strings); ++i) { |
88 | 0 | nsrefcnt count = NS_GetNumberOfAtoms(); |
89 | 0 |
|
90 | 0 | { |
91 | 0 | RefPtr<nsAtom> atom8 = NS_Atomize(Invalid8Strings[i].m8); |
92 | 0 | RefPtr<nsAtom> atom16 = NS_Atomize(Invalid8Strings[i].m16); |
93 | 0 | EXPECT_EQ(atom16, atom8); |
94 | 0 | EXPECT_TRUE(atom16->Equals(nsDependentString(Invalid8Strings[i].m16))); |
95 | 0 | } |
96 | 0 |
|
97 | 0 | EXPECT_EQ(count, NS_GetNumberOfAtoms()); |
98 | 0 | } |
99 | 0 |
|
100 | 0 | for (unsigned int i = 0; i < ArrayLength(Malformed8Strings); ++i) { |
101 | 0 | nsrefcnt count = NS_GetNumberOfAtoms(); |
102 | 0 |
|
103 | 0 | { |
104 | 0 | RefPtr<nsAtom> atom8 = NS_Atomize(Malformed8Strings[i].m8); |
105 | 0 | RefPtr<nsAtom> atom16 = NS_Atomize(Malformed8Strings[i].m16); |
106 | 0 | EXPECT_EQ(atom8, atom16); |
107 | 0 | } |
108 | 0 |
|
109 | 0 | EXPECT_EQ(count, NS_GetNumberOfAtoms()); |
110 | 0 | } |
111 | 0 | #endif |
112 | 0 | } |
113 | | |
114 | | #define FIRST_ATOM_STR "first static atom. Hello!" |
115 | | #define SECOND_ATOM_STR "second static atom. @World!" |
116 | 0 | #define THIRD_ATOM_STR "third static atom?!" |
117 | | |
118 | | bool |
119 | | isStaticAtom(nsAtom* atom) |
120 | 0 | { |
121 | 0 | // Don't use logic && in order to ensure that all addrefs/releases are always |
122 | 0 | // run, even if one of the tests fail. This allows us to run this code on a |
123 | 0 | // non-static atom without affecting its refcount. |
124 | 0 | bool rv = (atom->AddRef() == 2); |
125 | 0 | rv &= (atom->AddRef() == 2); |
126 | 0 | rv &= (atom->AddRef() == 2); |
127 | 0 |
|
128 | 0 | rv &= (atom->Release() == 1); |
129 | 0 | rv &= (atom->Release() == 1); |
130 | 0 | rv &= (atom->Release() == 1); |
131 | 0 | return rv; |
132 | 0 | } |
133 | | |
134 | | TEST(Atoms, Table) |
135 | 0 | { |
136 | 0 | nsrefcnt count = NS_GetNumberOfAtoms(); |
137 | 0 |
|
138 | 0 | RefPtr<nsAtom> thirdDynamic = NS_Atomize(THIRD_ATOM_STR); |
139 | 0 |
|
140 | 0 | EXPECT_FALSE(isStaticAtom(thirdDynamic)); |
141 | 0 |
|
142 | 0 | EXPECT_TRUE(thirdDynamic); |
143 | 0 | EXPECT_EQ(NS_GetNumberOfAtoms(), count + 1); |
144 | 0 | } |
145 | | |
146 | | class nsAtomRunner final : public nsIRunnable |
147 | | { |
148 | | public: |
149 | | NS_DECL_THREADSAFE_ISUPPORTS |
150 | | |
151 | | NS_IMETHOD Run() final |
152 | 0 | { |
153 | 0 | for (int i = 0; i < 10000; i++) { |
154 | 0 | RefPtr<nsAtom> atom = NS_Atomize(u"A Testing Atom"); |
155 | 0 | } |
156 | 0 | return NS_OK; |
157 | 0 | } |
158 | | |
159 | | private: |
160 | 0 | ~nsAtomRunner() {} |
161 | | }; |
162 | | |
163 | | NS_IMPL_ISUPPORTS(nsAtomRunner, nsIRunnable) |
164 | | |
165 | | TEST(Atoms, ConcurrentAccessing) |
166 | 0 | { |
167 | 0 | static const size_t kThreadCount = 4; |
168 | 0 | // Force a GC before so that we don't have any unused atom. |
169 | 0 | NS_GetNumberOfAtoms(); |
170 | 0 | EXPECT_EQ(NS_GetUnusedAtomCount(), int32_t(0)); |
171 | 0 | nsCOMPtr<nsIThread> threads[kThreadCount]; |
172 | 0 | for (size_t i = 0; i < kThreadCount; i++) { |
173 | 0 | nsresult rv = NS_NewThread(getter_AddRefs(threads[i]), new nsAtomRunner); |
174 | 0 | EXPECT_TRUE(NS_SUCCEEDED(rv)); |
175 | 0 | } |
176 | 0 | for (size_t i = 0; i < kThreadCount; i++) { |
177 | 0 | threads[i]->Shutdown(); |
178 | 0 | } |
179 | 0 | // We should have one unused atom from this test. |
180 | 0 | EXPECT_EQ(NS_GetUnusedAtomCount(), int32_t(1)); |
181 | 0 | } |
182 | | |
183 | | } |