michael@0: /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #include "mozilla/ArrayUtils.h" michael@0: michael@0: #include "nsIAtom.h" michael@0: #include "nsString.h" michael@0: #include "UTFStrings.h" michael@0: #include "nsIServiceManager.h" michael@0: #include "nsStaticAtom.h" michael@0: michael@0: using namespace mozilla; michael@0: michael@0: namespace TestAtoms { michael@0: michael@0: bool michael@0: test_basic() michael@0: { michael@0: for (unsigned int i = 0; i < ArrayLength(ValidStrings); ++i) { michael@0: nsDependentString str16(ValidStrings[i].m16); michael@0: nsDependentCString str8(ValidStrings[i].m8); michael@0: michael@0: nsCOMPtr atom = do_GetAtom(str16); michael@0: michael@0: if (!atom->Equals(str16) || !atom->EqualsUTF8(str8)) michael@0: return false; michael@0: michael@0: nsString tmp16; michael@0: nsCString tmp8; michael@0: atom->ToString(tmp16); michael@0: atom->ToUTF8String(tmp8); michael@0: if (!str16.Equals(tmp16) || !str8.Equals(tmp8)) michael@0: return false; michael@0: michael@0: if (!nsDependentString(atom->GetUTF16String()).Equals(str16)) michael@0: return false; michael@0: michael@0: if (!nsAtomString(atom).Equals(str16) || michael@0: !nsDependentAtomString(atom).Equals(str16) || michael@0: !nsAtomCString(atom).Equals(str8)) michael@0: return false; michael@0: } michael@0: michael@0: return true; michael@0: } michael@0: michael@0: bool michael@0: test_16vs8() michael@0: { michael@0: for (unsigned int i = 0; i < ArrayLength(ValidStrings); ++i) { michael@0: nsCOMPtr atom16 = do_GetAtom(ValidStrings[i].m16); michael@0: nsCOMPtr atom8 = do_GetAtom(ValidStrings[i].m8); michael@0: if (atom16 != atom8) michael@0: return false; michael@0: } michael@0: michael@0: return true; michael@0: } michael@0: michael@0: bool michael@0: test_buffersharing() michael@0: { michael@0: nsString unique; michael@0: unique.AssignLiteral("this is a unique string !@#$"); michael@0: michael@0: nsCOMPtr atom = do_GetAtom(unique); michael@0: michael@0: return unique.get() == atom->GetUTF16String(); michael@0: } michael@0: michael@0: bool michael@0: test_null() michael@0: { michael@0: nsAutoString str(NS_LITERAL_STRING("string with a \0 char")); michael@0: nsDependentString strCut(str.get()); michael@0: michael@0: if (str.Equals(strCut)) michael@0: return false; michael@0: michael@0: nsCOMPtr atomCut = do_GetAtom(strCut); michael@0: nsCOMPtr atom = do_GetAtom(str); michael@0: michael@0: return atom->GetLength() == str.Length() && michael@0: atom->Equals(str) && michael@0: atom->EqualsUTF8(NS_ConvertUTF16toUTF8(str)) && michael@0: atom != atomCut && michael@0: atomCut->Equals(strCut); michael@0: } michael@0: michael@0: bool michael@0: test_invalid() michael@0: { michael@0: for (unsigned int i = 0; i < ArrayLength(Invalid16Strings); ++i) { michael@0: nsrefcnt count = NS_GetNumberOfAtoms(); michael@0: michael@0: { michael@0: nsCOMPtr atom16 = do_GetAtom(Invalid16Strings[i].m16); michael@0: if (!atom16->Equals(nsDependentString(Invalid16Strings[i].m16))) michael@0: return false; michael@0: } michael@0: michael@0: if (count != NS_GetNumberOfAtoms()) michael@0: return false; michael@0: } michael@0: michael@0: for (unsigned int i = 0; i < ArrayLength(Invalid8Strings); ++i) { michael@0: nsrefcnt count = NS_GetNumberOfAtoms(); michael@0: michael@0: { michael@0: nsCOMPtr atom8 = do_GetAtom(Invalid8Strings[i].m8); michael@0: nsCOMPtr atom16 = do_GetAtom(Invalid8Strings[i].m16); michael@0: if (atom16 != atom8 || michael@0: !atom16->Equals(nsDependentString(Invalid8Strings[i].m16))) michael@0: return false; michael@0: } michael@0: michael@0: if (count != NS_GetNumberOfAtoms()) michael@0: return false; michael@0: } michael@0: michael@0: // Don't run this test in debug builds as that intentionally asserts. michael@0: #ifndef DEBUG michael@0: nsCOMPtr emptyAtom = do_GetAtom(""); michael@0: michael@0: for (unsigned int i = 0; i < ArrayLength(Malformed8Strings); ++i) { michael@0: nsrefcnt count = NS_GetNumberOfAtoms(); michael@0: michael@0: nsCOMPtr atom8 = do_GetAtom(Malformed8Strings[i]); michael@0: if (atom8 != emptyAtom || michael@0: count != NS_GetNumberOfAtoms()) michael@0: return false; michael@0: } michael@0: #endif michael@0: michael@0: return true; michael@0: } michael@0: michael@0: #define FIRST_ATOM_STR "first static atom. Hello!" michael@0: #define SECOND_ATOM_STR "second static atom. @World!" michael@0: #define THIRD_ATOM_STR "third static atom?!" michael@0: michael@0: static nsIAtom* sAtom1 = 0; michael@0: static nsIAtom* sAtom2 = 0; michael@0: static nsIAtom* sAtom3 = 0; michael@0: NS_STATIC_ATOM_BUFFER(sAtom1_buffer, FIRST_ATOM_STR) michael@0: NS_STATIC_ATOM_BUFFER(sAtom2_buffer, SECOND_ATOM_STR) michael@0: NS_STATIC_ATOM_BUFFER(sAtom3_buffer, THIRD_ATOM_STR) michael@0: static const nsStaticAtom sAtoms_info[] = { michael@0: NS_STATIC_ATOM(sAtom1_buffer, &sAtom1), michael@0: NS_STATIC_ATOM(sAtom2_buffer, &sAtom2), michael@0: NS_STATIC_ATOM(sAtom3_buffer, &sAtom3), michael@0: }; michael@0: michael@0: bool michael@0: isStaticAtom(nsIAtom* atom) michael@0: { michael@0: // Don't use logic && in order to ensure that all addrefs/releases are always michael@0: // run, even if one of the tests fail. This allows us to run this code on a michael@0: // non-static atom without affecting its refcount. michael@0: return (atom->AddRef() == 2) & michael@0: (atom->AddRef() == 2) & michael@0: (atom->AddRef() == 2) & michael@0: (atom->Release() == 1) & michael@0: (atom->Release() == 1) & michael@0: (atom->Release() == 1); michael@0: } michael@0: michael@0: bool michael@0: test_atomtable() michael@0: { michael@0: nsrefcnt count = NS_GetNumberOfAtoms(); michael@0: michael@0: nsCOMPtr thirdNonPerm = do_GetAtom(THIRD_ATOM_STR); michael@0: michael@0: if (isStaticAtom(thirdNonPerm)) michael@0: return false; michael@0: michael@0: if (!thirdNonPerm || NS_GetNumberOfAtoms() != count + 1) michael@0: return false; michael@0: michael@0: NS_RegisterStaticAtoms(sAtoms_info); michael@0: michael@0: return sAtom1 && michael@0: sAtom1->Equals(NS_LITERAL_STRING(FIRST_ATOM_STR)) && michael@0: isStaticAtom(sAtom1) && michael@0: sAtom2 && michael@0: sAtom2->Equals(NS_LITERAL_STRING(SECOND_ATOM_STR)) && michael@0: isStaticAtom(sAtom2) && michael@0: sAtom3 && michael@0: sAtom3->Equals(NS_LITERAL_STRING(THIRD_ATOM_STR)) && michael@0: isStaticAtom(sAtom3) && michael@0: NS_GetNumberOfAtoms() == count + 3 && michael@0: thirdNonPerm == sAtom3; michael@0: } michael@0: michael@0: #define FIRST_PERM_ATOM_STR "first permanent atom. Hello!" michael@0: #define SECOND_PERM_ATOM_STR "second permanent atom. @World!" michael@0: michael@0: bool michael@0: test_permanent() michael@0: { michael@0: nsrefcnt count = NS_GetNumberOfAtoms(); michael@0: michael@0: { michael@0: nsCOMPtr first = do_GetAtom(FIRST_PERM_ATOM_STR); michael@0: if (!first->Equals(NS_LITERAL_STRING(FIRST_PERM_ATOM_STR)) || michael@0: isStaticAtom(first)) michael@0: return false; michael@0: michael@0: nsCOMPtr first_p = michael@0: NS_NewPermanentAtom(NS_LITERAL_STRING(FIRST_PERM_ATOM_STR)); michael@0: if (!first_p->Equals(NS_LITERAL_STRING(FIRST_PERM_ATOM_STR)) || michael@0: !isStaticAtom(first_p) || michael@0: first != first_p) michael@0: return false; michael@0: michael@0: nsCOMPtr second_p = michael@0: NS_NewPermanentAtom(NS_LITERAL_STRING(SECOND_PERM_ATOM_STR)); michael@0: if (!second_p->Equals(NS_LITERAL_STRING(SECOND_PERM_ATOM_STR)) || michael@0: !isStaticAtom(second_p)) michael@0: return false; michael@0: michael@0: nsCOMPtr second = do_GetAtom(SECOND_PERM_ATOM_STR); michael@0: if (!second->Equals(NS_LITERAL_STRING(SECOND_PERM_ATOM_STR)) || michael@0: !isStaticAtom(second) || michael@0: second != second_p) michael@0: return false; michael@0: } michael@0: michael@0: return NS_GetNumberOfAtoms() == count + 2; michael@0: } michael@0: michael@0: typedef bool (*TestFunc)(); michael@0: michael@0: static const struct Test michael@0: { michael@0: const char* name; michael@0: TestFunc func; michael@0: } michael@0: tests[] = michael@0: { michael@0: { "test_basic", test_basic }, michael@0: { "test_16vs8", test_16vs8 }, michael@0: { "test_buffersharing", test_buffersharing }, michael@0: { "test_null", test_null }, michael@0: { "test_invalid", test_invalid }, michael@0: // FIXME: Bug 577500 TestAtoms fails when run in dist/bin due to michael@0: // static atom table already being closed. TestStaticAtoms has similar michael@0: // failure. michael@0: #if 0 michael@0: { "test_atomtable", test_atomtable }, michael@0: { "test_permanent", test_permanent }, michael@0: #endif michael@0: { nullptr, nullptr } michael@0: }; michael@0: michael@0: } michael@0: michael@0: using namespace TestAtoms; michael@0: michael@0: int main() michael@0: { michael@0: { michael@0: nsCOMPtr servMan; michael@0: NS_InitXPCOM2(getter_AddRefs(servMan), nullptr, nullptr); michael@0: michael@0: for (const Test* t = tests; t->name != nullptr; ++t) michael@0: { michael@0: printf("%25s : %s\n", t->name, t->func() ? "SUCCESS" : "FAILURE <--"); michael@0: } michael@0: } michael@0: michael@0: NS_ShutdownXPCOM(nullptr); michael@0: michael@0: return 0; michael@0: }