xpcom/tests/TestTArray.cpp

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/xpcom/tests/TestTArray.cpp	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,1066 @@
     1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     1.5 +/* vim:set ts=2 sw=2 sts=2 et cindent: */
     1.6 +/* This Source Code Form is subject to the terms of the Mozilla Public
     1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.8 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.9 +
    1.10 +#include "mozilla/ArrayUtils.h"
    1.11 +
    1.12 +#include <stdlib.h>
    1.13 +#include <stdio.h>
    1.14 +#include "nsTArray.h"
    1.15 +#include "nsAutoPtr.h"
    1.16 +#include "nsStringAPI.h"
    1.17 +#include "nsDirectoryServiceDefs.h"
    1.18 +#include "nsDirectoryServiceUtils.h"
    1.19 +#include "nsComponentManagerUtils.h"
    1.20 +#include "nsXPCOM.h"
    1.21 +#include "nsIFile.h"
    1.22 +
    1.23 +using namespace mozilla;
    1.24 +
    1.25 +namespace TestTArray {
    1.26 +
    1.27 +// Define this so we can use test_basic_array in test_comptr_array
    1.28 +template <class T>
    1.29 +inline bool operator<(const nsCOMPtr<T>& lhs, const nsCOMPtr<T>& rhs) {
    1.30 +  return lhs.get() < rhs.get();
    1.31 +}
    1.32 +
    1.33 +//----
    1.34 +
    1.35 +template <class ElementType>
    1.36 +static bool test_basic_array(ElementType *data,
    1.37 +                               uint32_t dataLen,
    1.38 +                               const ElementType& extra) {
    1.39 +  nsTArray<ElementType> ary;
    1.40 +  ary.AppendElements(data, dataLen);
    1.41 +  if (ary.Length() != dataLen) {
    1.42 +    return false;
    1.43 +  }
    1.44 +  if (!(ary == ary)) {
    1.45 +    return false;
    1.46 +  }
    1.47 +  uint32_t i;
    1.48 +  for (i = 0; i < ary.Length(); ++i) {
    1.49 +    if (ary[i] != data[i])
    1.50 +      return false;
    1.51 +  }
    1.52 +  for (i = 0; i < ary.Length(); ++i) {
    1.53 +    if (ary.SafeElementAt(i, extra) != data[i])
    1.54 +      return false;
    1.55 +  }
    1.56 +  if (ary.SafeElementAt(ary.Length(), extra) != extra ||
    1.57 +      ary.SafeElementAt(ary.Length() * 10, extra) != extra)
    1.58 +    return false;
    1.59 +  // ensure sort results in ascending order
    1.60 +  ary.Sort();
    1.61 +  uint32_t j = 0, k = ary.IndexOfFirstElementGt(extra);
    1.62 +  if (k != 0 && ary[k-1] == extra)
    1.63 +    return false;
    1.64 +  for (i = 0; i < ary.Length(); ++i) {
    1.65 +    k = ary.IndexOfFirstElementGt(ary[i]);
    1.66 +    if (k == 0 || ary[k-1] != ary[i])
    1.67 +      return false;
    1.68 +    if (k < j)
    1.69 +      return false;
    1.70 +    j = k;
    1.71 +  }
    1.72 +  for (i = ary.Length(); --i; ) {
    1.73 +    if (ary[i] < ary[i - 1])
    1.74 +      return false;
    1.75 +    if (ary[i] == ary[i - 1])
    1.76 +      ary.RemoveElementAt(i);
    1.77 +  }
    1.78 +  if (!(ary == ary)) {
    1.79 +    return false;
    1.80 +  }
    1.81 +  for (i = 0; i < ary.Length(); ++i) {
    1.82 +    if (ary.BinaryIndexOf(ary[i]) != i)
    1.83 +      return false;
    1.84 +  }
    1.85 +  if (ary.BinaryIndexOf(extra) != ary.NoIndex)
    1.86 +    return false;
    1.87 +  uint32_t oldLen = ary.Length();
    1.88 +  ary.RemoveElement(data[dataLen / 2]);
    1.89 +  if (ary.Length() != (oldLen - 1))
    1.90 +    return false;
    1.91 +  if (!(ary == ary))
    1.92 +    return false;
    1.93 +
    1.94 +  uint32_t index = ary.Length() / 2;
    1.95 +  if (!ary.InsertElementAt(index, extra))
    1.96 +    return false;
    1.97 +  if (!(ary == ary))
    1.98 +    return false;
    1.99 +  if (ary[index] != extra)
   1.100 +    return false;
   1.101 +  if (ary.IndexOf(extra) == UINT32_MAX)
   1.102 +    return false;
   1.103 +  if (ary.LastIndexOf(extra) == UINT32_MAX)
   1.104 +    return false;
   1.105 +  // ensure proper searching
   1.106 +  if (ary.IndexOf(extra) > ary.LastIndexOf(extra))
   1.107 +    return false;
   1.108 +  if (ary.IndexOf(extra, index) != ary.LastIndexOf(extra, index))
   1.109 +    return false;
   1.110 +
   1.111 +  nsTArray<ElementType> copy(ary);
   1.112 +  if (!(ary == copy))
   1.113 +    return false;
   1.114 +  for (i = 0; i < copy.Length(); ++i) {
   1.115 +    if (ary[i] != copy[i])
   1.116 +      return false;
   1.117 +  }
   1.118 +  if (!ary.AppendElements(copy))
   1.119 +    return false;
   1.120 +  uint32_t cap = ary.Capacity();
   1.121 +  ary.RemoveElementsAt(copy.Length(), copy.Length());
   1.122 +  ary.Compact();
   1.123 +  if (ary.Capacity() == cap)
   1.124 +    return false;
   1.125 +
   1.126 +  ary.Clear();
   1.127 +  if (ary.IndexOf(extra) != UINT32_MAX)
   1.128 +    return false;
   1.129 +  if (ary.LastIndexOf(extra) != UINT32_MAX)
   1.130 +    return false;
   1.131 +
   1.132 +  ary.Clear();
   1.133 +  if (!ary.IsEmpty() || ary.Elements() == nullptr)
   1.134 +    return false;
   1.135 +  if (!(ary == nsTArray<ElementType>()))
   1.136 +    return false;
   1.137 +  if (ary == copy)
   1.138 +    return false;
   1.139 +  if (ary.SafeElementAt(0, extra) != extra ||
   1.140 +      ary.SafeElementAt(10, extra) != extra)
   1.141 +    return false;
   1.142 +
   1.143 +  ary = copy;
   1.144 +  if (!(ary == copy))
   1.145 +    return false;
   1.146 +  for (i = 0; i < copy.Length(); ++i) {
   1.147 +    if (ary[i] != copy[i])
   1.148 +      return false;
   1.149 +  }
   1.150 +
   1.151 +  if (!ary.InsertElementsAt(0, copy))
   1.152 +    return false;
   1.153 +  if (ary == copy)
   1.154 +    return false;
   1.155 +  ary.RemoveElementsAt(0, copy.Length());
   1.156 +  for (i = 0; i < copy.Length(); ++i) {
   1.157 +    if (ary[i] != copy[i])
   1.158 +      return false;
   1.159 +  }
   1.160 +
   1.161 +  // These shouldn't crash!
   1.162 +  nsTArray<ElementType> empty;
   1.163 +  ary.AppendElements(reinterpret_cast<ElementType *>(0), 0);
   1.164 +  ary.AppendElements(empty);
   1.165 +
   1.166 +  // See bug 324981
   1.167 +  ary.RemoveElement(extra);
   1.168 +  ary.RemoveElement(extra);
   1.169 +
   1.170 +  return true;
   1.171 +}
   1.172 +
   1.173 +static bool test_int_array() {
   1.174 +  int data[] = {4,6,8,2,4,1,5,7,3};
   1.175 +  return test_basic_array(data, ArrayLength(data), int(14));
   1.176 +}
   1.177 +
   1.178 +static bool test_int64_array() {
   1.179 +  int64_t data[] = {4,6,8,2,4,1,5,7,3};
   1.180 +  return test_basic_array(data, ArrayLength(data), int64_t(14));
   1.181 +}
   1.182 +
   1.183 +static bool test_char_array() {
   1.184 +  char data[] = {4,6,8,2,4,1,5,7,3};
   1.185 +  return test_basic_array(data, ArrayLength(data), char(14));
   1.186 +}
   1.187 +
   1.188 +static bool test_uint32_array() {
   1.189 +  uint32_t data[] = {4,6,8,2,4,1,5,7,3};
   1.190 +  return test_basic_array(data, ArrayLength(data), uint32_t(14));
   1.191 +}
   1.192 +
   1.193 +//----
   1.194 +
   1.195 +class Object {
   1.196 +  public:
   1.197 +    Object() : mNum(0) {
   1.198 +    }
   1.199 +    Object(const char *str, uint32_t num) : mStr(str), mNum(num) {
   1.200 +    }
   1.201 +    Object(const Object& other) : mStr(other.mStr), mNum(other.mNum) {
   1.202 +    }
   1.203 +    ~Object() {}
   1.204 +
   1.205 +    Object& operator=(const Object& other) {
   1.206 +      mStr = other.mStr;
   1.207 +      mNum = other.mNum;
   1.208 +      return *this;
   1.209 +    }
   1.210 +
   1.211 +    bool operator==(const Object& other) const {
   1.212 +      return mStr == other.mStr && mNum == other.mNum;
   1.213 +    }
   1.214 +
   1.215 +    bool operator<(const Object& other) const {
   1.216 +      // sort based on mStr only
   1.217 +      return mStr.Compare(other.mStr) < 0;
   1.218 +    }
   1.219 +
   1.220 +    const char *Str() const { return mStr.get(); }
   1.221 +    uint32_t Num() const { return mNum; }
   1.222 +
   1.223 +  private:
   1.224 +    nsCString mStr;
   1.225 +    uint32_t  mNum;
   1.226 +};
   1.227 +
   1.228 +static bool test_object_array() {
   1.229 +  nsTArray<Object> objArray;
   1.230 +  const char kdata[] = "hello world";
   1.231 +  uint32_t i;
   1.232 +  for (i = 0; i < ArrayLength(kdata); ++i) {
   1.233 +    char x[] = {kdata[i],'\0'};
   1.234 +    if (!objArray.AppendElement(Object(x, i)))
   1.235 +      return false;
   1.236 +  }
   1.237 +  for (i = 0; i < ArrayLength(kdata); ++i) {
   1.238 +    if (objArray[i].Str()[0] != kdata[i])
   1.239 +      return false;
   1.240 +    if (objArray[i].Num() != i)
   1.241 +      return false;
   1.242 +  }
   1.243 +  objArray.Sort();
   1.244 +  const char ksorted[] = "\0 dehllloorw";
   1.245 +  for (i = 0; i < ArrayLength(kdata)-1; ++i) {
   1.246 +    if (objArray[i].Str()[0] != ksorted[i])
   1.247 +      return false;
   1.248 +  }
   1.249 +  return true;
   1.250 +}
   1.251 +
   1.252 +// nsTArray<nsAutoPtr<T>> is not supported
   1.253 +#if 0
   1.254 +static bool test_autoptr_array() {
   1.255 +  nsTArray< nsAutoPtr<Object> > objArray;
   1.256 +  const char kdata[] = "hello world";
   1.257 +  for (uint32_t i = 0; i < ArrayLength(kdata); ++i) {
   1.258 +    char x[] = {kdata[i],'\0'};
   1.259 +    nsAutoPtr<Object> obj(new Object(x,i));
   1.260 +    if (!objArray.AppendElement(obj))  // XXX does not call copy-constructor for nsAutoPtr!!!
   1.261 +      return false;
   1.262 +    if (obj.get() == nullptr)
   1.263 +      return false;
   1.264 +    obj.forget();  // the array now owns the reference
   1.265 +  }
   1.266 +  for (uint32_t i = 0; i < ArrayLength(kdata); ++i) {
   1.267 +    if (objArray[i]->Str()[0] != kdata[i])
   1.268 +      return false;
   1.269 +    if (objArray[i]->Num() != i)
   1.270 +      return false;
   1.271 +  }
   1.272 +  return true;
   1.273 +}
   1.274 +#endif
   1.275 +
   1.276 +//----
   1.277 +
   1.278 +static bool test_string_array() {
   1.279 +  nsTArray<nsCString> strArray;
   1.280 +  const char kdata[] = "hello world";
   1.281 +  uint32_t i;
   1.282 +  for (i = 0; i < ArrayLength(kdata); ++i) {
   1.283 +    nsCString str;
   1.284 +    str.Assign(kdata[i]);
   1.285 +    if (!strArray.AppendElement(str))
   1.286 +      return false;
   1.287 +  }
   1.288 +  for (i = 0; i < ArrayLength(kdata); ++i) {
   1.289 +    if (strArray[i].CharAt(0) != kdata[i])
   1.290 +      return false;
   1.291 +  }
   1.292 +
   1.293 +  const char kextra[] = "foo bar";
   1.294 +  uint32_t oldLen = strArray.Length();
   1.295 +  if (!strArray.AppendElement(kextra))
   1.296 +    return false;
   1.297 +  strArray.RemoveElement(kextra);
   1.298 +  if (oldLen != strArray.Length())
   1.299 +    return false;
   1.300 +
   1.301 +  if (strArray.IndexOf("e") != 1)
   1.302 +    return false;
   1.303 +
   1.304 +  strArray.Sort();
   1.305 +  const char ksorted[] = "\0 dehllloorw";
   1.306 +  for (i = ArrayLength(kdata); i--; ) {
   1.307 +    if (strArray[i].CharAt(0) != ksorted[i])
   1.308 +      return false;
   1.309 +    if (i > 0 && strArray[i] == strArray[i - 1])
   1.310 +      strArray.RemoveElementAt(i);
   1.311 +  }
   1.312 +  for (i = 0; i < strArray.Length(); ++i) {
   1.313 +    if (strArray.BinaryIndexOf(strArray[i]) != i)
   1.314 +      return false;
   1.315 +  }
   1.316 +  if (strArray.BinaryIndexOf(EmptyCString()) != strArray.NoIndex)
   1.317 +    return false;
   1.318 +
   1.319 +  nsCString rawArray[MOZ_ARRAY_LENGTH(kdata) - 1];
   1.320 +  for (i = 0; i < ArrayLength(rawArray); ++i)
   1.321 +    rawArray[i].Assign(kdata + i);  // substrings of kdata
   1.322 +  return test_basic_array(rawArray, ArrayLength(rawArray),
   1.323 +                          nsCString("foopy"));
   1.324 +}
   1.325 +
   1.326 +//----
   1.327 +
   1.328 +typedef nsCOMPtr<nsIFile> FilePointer;
   1.329 +
   1.330 +class nsFileNameComparator {
   1.331 +  public:
   1.332 +    bool Equals(const FilePointer &a, const char *b) const {
   1.333 +      nsAutoCString name;
   1.334 +      a->GetNativeLeafName(name);
   1.335 +      return name.Equals(b);
   1.336 +    }
   1.337 +};
   1.338 +
   1.339 +static bool test_comptr_array() {
   1.340 +  FilePointer tmpDir;
   1.341 +  NS_GetSpecialDirectory(NS_OS_TEMP_DIR, getter_AddRefs(tmpDir));
   1.342 +  if (!tmpDir)
   1.343 +    return false;
   1.344 +  const char *kNames[] = {
   1.345 +    "foo.txt", "bar.html", "baz.gif"
   1.346 +  };
   1.347 +  nsTArray<FilePointer> fileArray;
   1.348 +  uint32_t i;
   1.349 +  for (i = 0; i < ArrayLength(kNames); ++i) {
   1.350 +    FilePointer f;
   1.351 +    tmpDir->Clone(getter_AddRefs(f));
   1.352 +    if (!f)
   1.353 +      return false;
   1.354 +    if (NS_FAILED(f->AppendNative(nsDependentCString(kNames[i]))))
   1.355 +      return false;
   1.356 +    fileArray.AppendElement(f);
   1.357 +  }
   1.358 +
   1.359 +  if (fileArray.IndexOf(kNames[1], 0, nsFileNameComparator()) != 1)
   1.360 +    return false;
   1.361 +
   1.362 +  // It's unclear what 'operator<' means for nsCOMPtr, but whatever...
   1.363 +  return test_basic_array(fileArray.Elements(), fileArray.Length(), 
   1.364 +                          tmpDir);
   1.365 +}
   1.366 +
   1.367 +//----
   1.368 +
   1.369 +class RefcountedObject {
   1.370 +  public:
   1.371 +    RefcountedObject() : rc(0) {}
   1.372 +    void AddRef() {
   1.373 +      ++rc;
   1.374 +    }
   1.375 +    void Release() {
   1.376 +      if (--rc == 0)
   1.377 +        delete this;
   1.378 +    }
   1.379 +    ~RefcountedObject() {}
   1.380 +  private:
   1.381 +    int32_t rc;
   1.382 +};
   1.383 +
   1.384 +static bool test_refptr_array() {
   1.385 +  bool rv = true;
   1.386 +
   1.387 +  nsTArray< nsRefPtr<RefcountedObject> > objArray;
   1.388 +
   1.389 +  RefcountedObject *a = new RefcountedObject(); a->AddRef();
   1.390 +  RefcountedObject *b = new RefcountedObject(); b->AddRef();
   1.391 +  RefcountedObject *c = new RefcountedObject(); c->AddRef();
   1.392 +
   1.393 +  objArray.AppendElement(a);
   1.394 +  objArray.AppendElement(b);
   1.395 +  objArray.AppendElement(c);
   1.396 +
   1.397 +  if (objArray.IndexOf(b) != 1)
   1.398 +    rv = false;
   1.399 +
   1.400 +  a->Release();
   1.401 +  b->Release();
   1.402 +  c->Release();
   1.403 +  return rv;
   1.404 +}
   1.405 +
   1.406 +//----
   1.407 +
   1.408 +static bool test_ptrarray() {
   1.409 +  nsTArray<uint32_t*> ary;
   1.410 +  if (ary.SafeElementAt(0) != nullptr)
   1.411 +    return false;
   1.412 +  if (ary.SafeElementAt(1000) != nullptr)
   1.413 +    return false;
   1.414 +  uint32_t a = 10;
   1.415 +  ary.AppendElement(&a);
   1.416 +  if (*ary[0] != a)
   1.417 +    return false;
   1.418 +  if (*ary.SafeElementAt(0) != a)
   1.419 +    return false;
   1.420 +
   1.421 +  nsTArray<const uint32_t*> cary;
   1.422 +  if (cary.SafeElementAt(0) != nullptr)
   1.423 +    return false;
   1.424 +  if (cary.SafeElementAt(1000) != nullptr)
   1.425 +    return false;
   1.426 +  const uint32_t b = 14;
   1.427 +  cary.AppendElement(&a);
   1.428 +  cary.AppendElement(&b);
   1.429 +  if (*cary[0] != a || *cary[1] != b)
   1.430 +    return false;
   1.431 +  if (*cary.SafeElementAt(0) != a || *cary.SafeElementAt(1) != b)
   1.432 +    return false;
   1.433 +
   1.434 +  return true;
   1.435 +}
   1.436 +
   1.437 +//----
   1.438 +
   1.439 +// This test relies too heavily on the existence of DebugGetHeader to be
   1.440 +// useful in non-debug builds.
   1.441 +#ifdef DEBUG
   1.442 +static bool test_autoarray() {
   1.443 +  uint32_t data[] = {4,6,8,2,4,1,5,7,3};
   1.444 +  nsAutoTArray<uint32_t, MOZ_ARRAY_LENGTH(data)> array;
   1.445 +
   1.446 +  void* hdr = array.DebugGetHeader();
   1.447 +  if (hdr == nsTArray<uint32_t>().DebugGetHeader())
   1.448 +    return false;
   1.449 +  if (hdr == nsAutoTArray<uint32_t, MOZ_ARRAY_LENGTH(data)>().DebugGetHeader())
   1.450 +    return false;
   1.451 +
   1.452 +  array.AppendElement(1u);
   1.453 +  if (hdr != array.DebugGetHeader())
   1.454 +    return false;
   1.455 +
   1.456 +  array.RemoveElement(1u);
   1.457 +  array.AppendElements(data, ArrayLength(data));
   1.458 +  if (hdr != array.DebugGetHeader())
   1.459 +    return false;
   1.460 +
   1.461 +  array.AppendElement(2u);
   1.462 +  if (hdr == array.DebugGetHeader())
   1.463 +    return false;
   1.464 +
   1.465 +  array.Clear();
   1.466 +  array.Compact();
   1.467 +  if (hdr != array.DebugGetHeader())
   1.468 +    return false;
   1.469 +  array.AppendElements(data, ArrayLength(data));
   1.470 +  if (hdr != array.DebugGetHeader())
   1.471 +    return false;
   1.472 +
   1.473 +  nsTArray<uint32_t> array2;
   1.474 +  void* emptyHdr = array2.DebugGetHeader();
   1.475 +  array.SwapElements(array2);
   1.476 +  if (emptyHdr == array.DebugGetHeader())
   1.477 +    return false;
   1.478 +  if (hdr == array2.DebugGetHeader())
   1.479 +    return false;
   1.480 +  uint32_t i;
   1.481 +  for (i = 0; i < ArrayLength(data); ++i) {
   1.482 +    if (array2[i] != data[i])
   1.483 +      return false;
   1.484 +  }
   1.485 +  if (!array.IsEmpty())
   1.486 +    return false;
   1.487 +
   1.488 +  array.Compact();
   1.489 +  array.AppendElements(data, ArrayLength(data));
   1.490 +  uint32_t data3[] = {5, 7, 11};
   1.491 +  nsAutoTArray<uint32_t, MOZ_ARRAY_LENGTH(data3)> array3;
   1.492 +  array3.AppendElements(data3, ArrayLength(data3));  
   1.493 +  array.SwapElements(array3);
   1.494 +  for (i = 0; i < ArrayLength(data); ++i) {
   1.495 +    if (array3[i] != data[i])
   1.496 +      return false;
   1.497 +  }
   1.498 +  for (i = 0; i < ArrayLength(data3); ++i) {
   1.499 +    if (array[i] != data3[i])
   1.500 +      return false;
   1.501 +  }
   1.502 +
   1.503 +  return true;
   1.504 +}
   1.505 +#endif
   1.506 +
   1.507 +//----
   1.508 +
   1.509 +// IndexOf used to potentially scan beyond the end of the array.  Test for
   1.510 +// this incorrect behavior by adding a value (5), removing it, then seeing
   1.511 +// if IndexOf finds it.
   1.512 +static bool test_indexof() {
   1.513 +  nsTArray<int> array;
   1.514 +  array.AppendElement(0);
   1.515 +  // add and remove the 5
   1.516 +  array.AppendElement(5);
   1.517 +  array.RemoveElementAt(1);
   1.518 +  // we should not find the 5!
   1.519 +  return array.IndexOf(5, 1) == array.NoIndex;
   1.520 +}
   1.521 +
   1.522 +//----
   1.523 +
   1.524 +template <class Array>
   1.525 +static bool is_heap(const Array& ary, uint32_t len) {
   1.526 +  uint32_t index = 1;
   1.527 +  while (index < len) {
   1.528 +    if (ary[index] > ary[(index - 1) >> 1])
   1.529 +      return false;
   1.530 +    index++;
   1.531 +  }
   1.532 +  return true;
   1.533 +} 
   1.534 +
   1.535 +static bool test_heap() {
   1.536 +  const int data[] = {4,6,8,2,4,1,5,7,3};
   1.537 +  nsTArray<int> ary;
   1.538 +  ary.AppendElements(data, ArrayLength(data));
   1.539 +  // make a heap and make sure it's a heap
   1.540 +  ary.MakeHeap();
   1.541 +  if (!is_heap(ary, ArrayLength(data)))
   1.542 +    return false;
   1.543 +  // pop the root and make sure it's still a heap
   1.544 +  int root = ary[0];
   1.545 +  ary.PopHeap();
   1.546 +  if (!is_heap(ary, ArrayLength(data) - 1))
   1.547 +    return false;
   1.548 +  // push the previously poped value back on and make sure it's still a heap
   1.549 +  ary.PushHeap(root);
   1.550 +  if (!is_heap(ary, ArrayLength(data)))
   1.551 +    return false;
   1.552 +  // make sure the heap looks like what we expect
   1.553 +  const int expected_data[] = {8,7,5,6,4,1,4,2,3};
   1.554 +  uint32_t index;
   1.555 +  for (index = 0; index < ArrayLength(data); index++)
   1.556 +    if (ary[index] != expected_data[index])
   1.557 +      return false;
   1.558 +  return true;
   1.559 +}
   1.560 +
   1.561 +//----
   1.562 +
   1.563 +// An array |arr| is using its auto buffer if |&arr < arr.Elements()| and
   1.564 +// |arr.Elements() - &arr| is small.
   1.565 +
   1.566 +#define IS_USING_AUTO(arr) \
   1.567 +  ((uintptr_t) &(arr) < (uintptr_t) arr.Elements() && \
   1.568 +   ((ptrdiff_t)arr.Elements() - (ptrdiff_t)&arr) <= 16)
   1.569 +
   1.570 +#define CHECK_IS_USING_AUTO(arr) \
   1.571 +  do {                                                    \
   1.572 +    if (!(IS_USING_AUTO(arr))) {                          \
   1.573 +      printf("%s:%d CHECK_IS_USING_AUTO(%s) failed.\n",   \
   1.574 +             __FILE__, __LINE__, #arr);                   \
   1.575 +      return false;                                    \
   1.576 +    }                                                     \
   1.577 +  } while(0)
   1.578 +
   1.579 +#define CHECK_NOT_USING_AUTO(arr) \
   1.580 +  do {                                                    \
   1.581 +    if (IS_USING_AUTO(arr)) {                             \
   1.582 +      printf("%s:%d CHECK_NOT_USING_AUTO(%s) failed.\n",  \
   1.583 +             __FILE__, __LINE__, #arr);                   \
   1.584 +      return false;                                    \
   1.585 +    }                                                     \
   1.586 +  } while(0)
   1.587 +
   1.588 +#define CHECK_USES_SHARED_EMPTY_HDR(arr) \
   1.589 +  do {                                                    \
   1.590 +    nsTArray<int> _empty;                                 \
   1.591 +    if (_empty.Elements() != arr.Elements()) {            \
   1.592 +      printf("%s:%d CHECK_USES_EMPTY_HDR(%s) failed.\n",  \
   1.593 +             __FILE__, __LINE__, #arr);                   \
   1.594 +      return false;                                    \
   1.595 +    }                                                     \
   1.596 +  } while(0)
   1.597 +
   1.598 +#define CHECK_EQ_INT(actual, expected) \
   1.599 +  do {                                                                       \
   1.600 +    if ((actual) != (expected)) {                                            \
   1.601 +      printf("%s:%d CHECK_EQ_INT(%s=%u, %s=%u) failed.\n",                   \
   1.602 +             __FILE__, __LINE__, #actual, (actual), #expected, (expected));  \
   1.603 +      return false;                                                       \
   1.604 +    }                                                                        \
   1.605 +  } while(0)
   1.606 +
   1.607 +#define CHECK_ARRAY(arr, data) \
   1.608 +  do {                                                          \
   1.609 +    CHECK_EQ_INT((arr).Length(), (uint32_t)ArrayLength(data));  \
   1.610 +    for (uint32_t _i = 0; _i < ArrayLength(data); _i++) {       \
   1.611 +      CHECK_EQ_INT((arr)[_i], (data)[_i]);                      \
   1.612 +    }                                                           \
   1.613 +  } while(0)
   1.614 +
   1.615 +static bool test_swap() {
   1.616 +  // Test nsTArray::SwapElements.  Unfortunately there are many cases.
   1.617 +  int data1[] = {8, 6, 7, 5};
   1.618 +  int data2[] = {3, 0, 9};
   1.619 +
   1.620 +  // Swap two auto arrays.
   1.621 +  {
   1.622 +    nsAutoTArray<int, 8> a;
   1.623 +    nsAutoTArray<int, 6> b;
   1.624 +
   1.625 +    a.AppendElements(data1, ArrayLength(data1));
   1.626 +    b.AppendElements(data2, ArrayLength(data2));
   1.627 +    CHECK_IS_USING_AUTO(a);
   1.628 +    CHECK_IS_USING_AUTO(b);
   1.629 +
   1.630 +    a.SwapElements(b);
   1.631 +
   1.632 +    CHECK_IS_USING_AUTO(a);
   1.633 +    CHECK_IS_USING_AUTO(b);
   1.634 +    CHECK_ARRAY(a, data2);
   1.635 +    CHECK_ARRAY(b, data1);
   1.636 +  }
   1.637 +
   1.638 +  // Swap two auto arrays -- one whose data lives on the heap, the other whose
   1.639 +  // data lives on the stack -- which each fits into the other's auto storage.
   1.640 +  {
   1.641 +    nsAutoTArray<int, 3> a;
   1.642 +    nsAutoTArray<int, 3> b;
   1.643 +
   1.644 +    a.AppendElements(data1, ArrayLength(data1));
   1.645 +    a.RemoveElementAt(3);
   1.646 +    b.AppendElements(data2, ArrayLength(data2));
   1.647 +
   1.648 +    // Here and elsewhere, we assert that if we start with an auto array
   1.649 +    // capable of storing N elements, we store N+1 elements into the array, and
   1.650 +    // then we remove one element, that array is still not using its auto
   1.651 +    // buffer.
   1.652 +    //
   1.653 +    // This isn't at all required by the TArray API. It would be fine if, when
   1.654 +    // we shrink back to N elements, the TArray frees its heap storage and goes
   1.655 +    // back to using its stack storage.  But we assert here as a check that the
   1.656 +    // test does what we expect.  If the TArray implementation changes, just
   1.657 +    // change the failing assertions.
   1.658 +    CHECK_NOT_USING_AUTO(a);
   1.659 +
   1.660 +    // This check had better not change, though.
   1.661 +    CHECK_IS_USING_AUTO(b);
   1.662 +
   1.663 +    a.SwapElements(b);
   1.664 +
   1.665 +    CHECK_IS_USING_AUTO(b);
   1.666 +    CHECK_ARRAY(a, data2);
   1.667 +    int expectedB[] = {8, 6, 7};
   1.668 +    CHECK_ARRAY(b, expectedB);
   1.669 +  }
   1.670 +
   1.671 +  // Swap two auto arrays which are using heap storage such that one fits into
   1.672 +  // the other's auto storage, but the other needs to stay on the heap.
   1.673 +  {
   1.674 +    nsAutoTArray<int, 3> a;
   1.675 +    nsAutoTArray<int, 2> b;
   1.676 +    a.AppendElements(data1, ArrayLength(data1));
   1.677 +    a.RemoveElementAt(3);
   1.678 +
   1.679 +    b.AppendElements(data2, ArrayLength(data2));
   1.680 +    b.RemoveElementAt(2);
   1.681 +
   1.682 +    CHECK_NOT_USING_AUTO(a);
   1.683 +    CHECK_NOT_USING_AUTO(b);
   1.684 +
   1.685 +    a.SwapElements(b);
   1.686 +
   1.687 +    CHECK_NOT_USING_AUTO(b);
   1.688 +
   1.689 +    int expected1[] = {3, 0};
   1.690 +    int expected2[] = {8, 6, 7};
   1.691 +
   1.692 +    CHECK_ARRAY(a, expected1);
   1.693 +    CHECK_ARRAY(b, expected2);
   1.694 +  }
   1.695 +
   1.696 +  // Swap two arrays, neither of which fits into the other's auto-storage.
   1.697 +  {
   1.698 +    nsAutoTArray<int, 1> a;
   1.699 +    nsAutoTArray<int, 3> b;
   1.700 +
   1.701 +    a.AppendElements(data1, ArrayLength(data1));
   1.702 +    b.AppendElements(data2, ArrayLength(data2));
   1.703 +
   1.704 +    a.SwapElements(b);
   1.705 +
   1.706 +    CHECK_ARRAY(a, data2);
   1.707 +    CHECK_ARRAY(b, data1);
   1.708 +  }
   1.709 +
   1.710 +  // Swap an empty nsTArray with a non-empty nsAutoTArray.
   1.711 +  {
   1.712 +    nsTArray<int> a;
   1.713 +    nsAutoTArray<int, 3> b;
   1.714 +
   1.715 +    b.AppendElements(data2, ArrayLength(data2));
   1.716 +    CHECK_IS_USING_AUTO(b);
   1.717 +
   1.718 +    a.SwapElements(b);
   1.719 +
   1.720 +    CHECK_ARRAY(a, data2);
   1.721 +    CHECK_EQ_INT(b.Length(), 0);
   1.722 +    CHECK_IS_USING_AUTO(b);
   1.723 +  }
   1.724 +
   1.725 +  // Swap two big auto arrays.
   1.726 +  {
   1.727 +    const unsigned size = 8192;
   1.728 +    nsAutoTArray<unsigned, size> a;
   1.729 +    nsAutoTArray<unsigned, size> b;
   1.730 +
   1.731 +    for (unsigned i = 0; i < size; i++) {
   1.732 +      a.AppendElement(i);
   1.733 +      b.AppendElement(i + 1);
   1.734 +    }
   1.735 +
   1.736 +    CHECK_IS_USING_AUTO(a);
   1.737 +    CHECK_IS_USING_AUTO(b);
   1.738 +
   1.739 +    a.SwapElements(b);
   1.740 +
   1.741 +    CHECK_IS_USING_AUTO(a);
   1.742 +    CHECK_IS_USING_AUTO(b);
   1.743 +
   1.744 +    CHECK_EQ_INT(a.Length(), size);
   1.745 +    CHECK_EQ_INT(b.Length(), size);
   1.746 +
   1.747 +    for (unsigned i = 0; i < size; i++) {
   1.748 +      CHECK_EQ_INT(a[i], i + 1);
   1.749 +      CHECK_EQ_INT(b[i], i);
   1.750 +    }
   1.751 +  }
   1.752 +
   1.753 +  // Swap two arrays and make sure that their capacities don't increase
   1.754 +  // unnecessarily.
   1.755 +  {
   1.756 +    nsTArray<int> a;
   1.757 +    nsTArray<int> b;
   1.758 +    b.AppendElements(data2, ArrayLength(data2));
   1.759 +
   1.760 +    CHECK_EQ_INT(a.Capacity(), 0);
   1.761 +    uint32_t bCapacity = b.Capacity();
   1.762 +
   1.763 +    a.SwapElements(b);
   1.764 +
   1.765 +    // Make sure that we didn't increase the capacity of either array.
   1.766 +    CHECK_ARRAY(a, data2);
   1.767 +    CHECK_EQ_INT(b.Length(), 0);
   1.768 +    CHECK_EQ_INT(b.Capacity(), 0);
   1.769 +    CHECK_EQ_INT(a.Capacity(), bCapacity);
   1.770 +  }
   1.771 +
   1.772 +  // Swap an auto array with a TArray, then clear the auto array and make sure
   1.773 +  // it doesn't forget the fact that it has an auto buffer.
   1.774 +  {
   1.775 +    nsTArray<int> a;
   1.776 +    nsAutoTArray<int, 3> b;
   1.777 +
   1.778 +    a.AppendElements(data1, ArrayLength(data1));
   1.779 +
   1.780 +    a.SwapElements(b);
   1.781 +
   1.782 +    CHECK_EQ_INT(a.Length(), 0);
   1.783 +    CHECK_ARRAY(b, data1);
   1.784 +
   1.785 +    b.Clear();
   1.786 +
   1.787 +    CHECK_USES_SHARED_EMPTY_HDR(a);
   1.788 +    CHECK_IS_USING_AUTO(b);
   1.789 +  }
   1.790 +
   1.791 +  // Same thing as the previous test, but with more auto arrays.
   1.792 +  {
   1.793 +    nsAutoTArray<int, 16> a;
   1.794 +    nsAutoTArray<int, 3> b;
   1.795 +
   1.796 +    a.AppendElements(data1, ArrayLength(data1));
   1.797 +
   1.798 +    a.SwapElements(b);
   1.799 +
   1.800 +    CHECK_EQ_INT(a.Length(), 0);
   1.801 +    CHECK_ARRAY(b, data1);
   1.802 +
   1.803 +    b.Clear();
   1.804 +
   1.805 +    CHECK_IS_USING_AUTO(a);
   1.806 +    CHECK_IS_USING_AUTO(b);
   1.807 +  }
   1.808 +
   1.809 +  // Swap an empty nsTArray and an empty nsAutoTArray.
   1.810 +  {
   1.811 +    nsAutoTArray<int, 8> a;
   1.812 +    nsTArray<int> b;
   1.813 +
   1.814 +    a.SwapElements(b);
   1.815 +
   1.816 +    CHECK_IS_USING_AUTO(a);
   1.817 +    CHECK_NOT_USING_AUTO(b);
   1.818 +    CHECK_EQ_INT(a.Length(), 0);
   1.819 +    CHECK_EQ_INT(b.Length(), 0);
   1.820 +  }
   1.821 +
   1.822 +  // Swap empty auto array with non-empty nsAutoTArray using malloc'ed storage.
   1.823 +  // I promise, all these tests have a point.
   1.824 +  {
   1.825 +    nsAutoTArray<int, 2> a;
   1.826 +    nsAutoTArray<int, 1> b;
   1.827 +
   1.828 +    a.AppendElements(data1, ArrayLength(data1));
   1.829 +
   1.830 +    a.SwapElements(b);
   1.831 +
   1.832 +    CHECK_IS_USING_AUTO(a);
   1.833 +    CHECK_NOT_USING_AUTO(b);
   1.834 +    CHECK_ARRAY(b, data1);
   1.835 +    CHECK_EQ_INT(a.Length(), 0);
   1.836 +  }
   1.837 +
   1.838 +  return true;
   1.839 +}
   1.840 +
   1.841 +static bool test_fallible()
   1.842 +{
   1.843 +  // Test that FallibleTArray works properly; that is, it never OOMs, but
   1.844 +  // instead eventually returns false.
   1.845 +  //
   1.846 +  // This test is only meaningful on 32-bit systems.  On a 64-bit system, we
   1.847 +  // might never OOM.
   1.848 +  if (sizeof(void*) > 4) {
   1.849 +    return true;
   1.850 +  }
   1.851 +
   1.852 +  // Allocate a bunch of 128MB arrays.  Larger allocations will fail on some
   1.853 +  // platforms without actually hitting OOM.
   1.854 +  //
   1.855 +  // 36 * 128MB > 4GB, so we should definitely OOM by the 36th array.
   1.856 +  const unsigned numArrays = 36;
   1.857 +  FallibleTArray<char> arrays[numArrays];
   1.858 +  for (uint32_t i = 0; i < numArrays; i++) {
   1.859 +    bool success = arrays[i].SetCapacity(128 * 1024 * 1024);
   1.860 +    if (!success) {
   1.861 +      // We got our OOM.  Check that it didn't come too early.
   1.862 +      if (i < 8) {
   1.863 +        printf("test_fallible: Got OOM on iteration %d.  Too early!\n", i);
   1.864 +        return false;
   1.865 +      }
   1.866 +      return true;
   1.867 +    }
   1.868 +  }
   1.869 +
   1.870 +  // No OOM?  That's...weird.
   1.871 +  printf("test_fallible: Didn't OOM or crash?  nsTArray::SetCapacity "
   1.872 +         "must be lying.\n");
   1.873 +  return false;
   1.874 +}
   1.875 +
   1.876 +static bool test_conversion_operator() {
   1.877 +  FallibleTArray<int> f;
   1.878 +  const FallibleTArray<int> fconst;
   1.879 +  AutoFallibleTArray<int, 8> fauto;
   1.880 +  const AutoFallibleTArray<int, 8> fautoconst;
   1.881 +
   1.882 +  InfallibleTArray<int> i;
   1.883 +  const InfallibleTArray<int> iconst;
   1.884 +  AutoInfallibleTArray<int, 8> iauto;
   1.885 +  const AutoInfallibleTArray<int, 8> iautoconst;
   1.886 +
   1.887 +  nsTArray<int> t;
   1.888 +  const nsTArray<int> tconst;
   1.889 +  nsAutoTArray<int, 8> tauto;
   1.890 +  const nsAutoTArray<int, 8> tautoconst;
   1.891 +
   1.892 +#define CHECK_ARRAY_CAST(type)                                 \
   1.893 +  do {                                                         \
   1.894 +    const type<int>& z1 = f;                                   \
   1.895 +    if ((void*)&z1 != (void*)&f) return false;                 \
   1.896 +    const type<int>& z2 = fconst;                              \
   1.897 +    if ((void*)&z2 != (void*)&fconst) return false;            \
   1.898 +    const type<int>& z3 = fauto;                               \
   1.899 +    if ((void*)&z3 != (void*)&fauto) return false;             \
   1.900 +    const type<int>& z4 = fautoconst;                          \
   1.901 +    if ((void*)&z4 != (void*)&fautoconst) return false;        \
   1.902 +    const type<int>& z5 = i;                                   \
   1.903 +    if ((void*)&z5 != (void*)&i) return false;                 \
   1.904 +    const type<int>& z6 = iconst;                              \
   1.905 +    if ((void*)&z6 != (void*)&iconst) return false;            \
   1.906 +    const type<int>& z7 = iauto;                               \
   1.907 +    if ((void*)&z7 != (void*)&iauto) return false;             \
   1.908 +    const type<int>& z8 = iautoconst;                          \
   1.909 +    if ((void*)&z8 != (void*)&iautoconst) return false;        \
   1.910 +    const type<int>& z9 = t;                                   \
   1.911 +    if ((void*)&z9 != (void*)&t) return false;                 \
   1.912 +    const type<int>& z10 = tconst;                             \
   1.913 +    if ((void*)&z10 != (void*)&tconst) return false;           \
   1.914 +    const type<int>& z11 = tauto;                              \
   1.915 +    if ((void*)&z11 != (void*)&tauto) return false;            \
   1.916 +    const type<int>& z12 = tautoconst;                         \
   1.917 +    if ((void*)&z12 != (void*)&tautoconst) return false;       \
   1.918 +  } while (0)
   1.919 +
   1.920 +  CHECK_ARRAY_CAST(FallibleTArray);
   1.921 +  CHECK_ARRAY_CAST(InfallibleTArray);
   1.922 +  CHECK_ARRAY_CAST(nsTArray);
   1.923 +
   1.924 +#undef CHECK_ARRAY_CAST
   1.925 +
   1.926 +  return true;
   1.927 +}
   1.928 +
   1.929 +template<class T>
   1.930 +struct BufAccessor : public T
   1.931 +{
   1.932 +  void* GetHdr() { return T::mHdr; }
   1.933 +};
   1.934 +
   1.935 +static bool test_SetLengthAndRetainStorage_no_ctor() {
   1.936 +  // 1050 because sizeof(int)*1050 is more than a page typically.
   1.937 +  const int N = 1050;
   1.938 +  FallibleTArray<int> f;
   1.939 +  AutoFallibleTArray<int, N> fauto;
   1.940 +
   1.941 +  InfallibleTArray<int> i;
   1.942 +  AutoInfallibleTArray<int, N> iauto;
   1.943 +
   1.944 +  nsTArray<int> t;
   1.945 +  nsAutoTArray<int, N> tauto;
   1.946 +
   1.947 +#define LPAREN (
   1.948 +#define RPAREN )
   1.949 +#define FOR_EACH(pre, post)                                    \
   1.950 +  do {                                                         \
   1.951 +    pre f post;                                                \
   1.952 +    pre fauto post;                                            \
   1.953 +    pre i post;                                                \
   1.954 +    pre iauto post;                                            \
   1.955 +    pre t post;                                                \
   1.956 +    pre tauto post;                                            \
   1.957 +  } while (0)
   1.958 +  
   1.959 +  // Setup test arrays.
   1.960 +  FOR_EACH(;, .SetLength(N));
   1.961 +  for (int n = 0; n < N; ++n) {
   1.962 +    FOR_EACH(;, [n] = n);
   1.963 +  }
   1.964 +
   1.965 +  void* initial_Hdrs[] = {
   1.966 +    static_cast<BufAccessor<FallibleTArray<int> >&>(f).GetHdr(),
   1.967 +    static_cast<BufAccessor<AutoFallibleTArray<int, N> >&>(fauto).GetHdr(),
   1.968 +    static_cast<BufAccessor<InfallibleTArray<int> >&>(i).GetHdr(),
   1.969 +    static_cast<BufAccessor<AutoInfallibleTArray<int, N> >&>(iauto).GetHdr(),
   1.970 +    static_cast<BufAccessor<nsTArray<int> >&>(t).GetHdr(),
   1.971 +    static_cast<BufAccessor<nsAutoTArray<int, N> >&>(tauto).GetHdr(),
   1.972 +    nullptr
   1.973 +  };
   1.974 +
   1.975 +  // SetLengthAndRetainStorage(n), should NOT overwrite memory when T hasn't
   1.976 +  // a default constructor.
   1.977 +  FOR_EACH(;, .SetLengthAndRetainStorage(8));
   1.978 +  FOR_EACH(;, .SetLengthAndRetainStorage(12));
   1.979 +  for (int n = 0; n < 12; ++n) {
   1.980 +    FOR_EACH(if LPAREN, [n] != n RPAREN return false);
   1.981 +  }
   1.982 +  FOR_EACH(;, .SetLengthAndRetainStorage(0));
   1.983 +  FOR_EACH(;, .SetLengthAndRetainStorage(N));
   1.984 +  for (int n = 0; n < N; ++n) {
   1.985 +    FOR_EACH(if LPAREN, [n] != n RPAREN return false);
   1.986 +  }
   1.987 +
   1.988 +  void* current_Hdrs[] = {
   1.989 +    static_cast<BufAccessor<FallibleTArray<int> >&>(f).GetHdr(),
   1.990 +    static_cast<BufAccessor<AutoFallibleTArray<int, N> >&>(fauto).GetHdr(),
   1.991 +    static_cast<BufAccessor<InfallibleTArray<int> >&>(i).GetHdr(),
   1.992 +    static_cast<BufAccessor<AutoInfallibleTArray<int, N> >&>(iauto).GetHdr(),
   1.993 +    static_cast<BufAccessor<nsTArray<int> >&>(t).GetHdr(),
   1.994 +    static_cast<BufAccessor<nsAutoTArray<int, N> >&>(tauto).GetHdr(),
   1.995 +    nullptr
   1.996 +  };
   1.997 +
   1.998 +  // SetLengthAndRetainStorage(n) should NOT have reallocated the internal
   1.999 +  // memory.
  1.1000 +  if (sizeof(initial_Hdrs) != sizeof(current_Hdrs)) return false;
  1.1001 +  for (size_t n = 0; n < sizeof(current_Hdrs) / sizeof(current_Hdrs[0]); ++n) {
  1.1002 +    if (current_Hdrs[n] != initial_Hdrs[n]) {
  1.1003 +      return false;
  1.1004 +    }
  1.1005 +  }
  1.1006 +
  1.1007 +
  1.1008 +#undef FOR_EACH
  1.1009 +#undef LPAREN
  1.1010 +#undef RPAREN
  1.1011 +
  1.1012 +  return true;
  1.1013 +}
  1.1014 +
  1.1015 +//----
  1.1016 +
  1.1017 +typedef bool (*TestFunc)();
  1.1018 +#define DECL_TEST(name) { #name, name }
  1.1019 +
  1.1020 +static const struct Test {
  1.1021 +  const char* name;
  1.1022 +  TestFunc    func;
  1.1023 +} tests[] = {
  1.1024 +  DECL_TEST(test_int_array),
  1.1025 +  DECL_TEST(test_int64_array),
  1.1026 +  DECL_TEST(test_char_array),
  1.1027 +  DECL_TEST(test_uint32_array),
  1.1028 +  DECL_TEST(test_object_array),
  1.1029 +  DECL_TEST(test_string_array),
  1.1030 +  DECL_TEST(test_comptr_array),
  1.1031 +  DECL_TEST(test_refptr_array),
  1.1032 +  DECL_TEST(test_ptrarray),
  1.1033 +#ifdef DEBUG
  1.1034 +  DECL_TEST(test_autoarray),
  1.1035 +#endif
  1.1036 +  DECL_TEST(test_indexof),
  1.1037 +  DECL_TEST(test_heap),
  1.1038 +  DECL_TEST(test_swap),
  1.1039 +  DECL_TEST(test_fallible),
  1.1040 +  DECL_TEST(test_conversion_operator),
  1.1041 +  DECL_TEST(test_SetLengthAndRetainStorage_no_ctor),
  1.1042 +  { nullptr, nullptr }
  1.1043 +};
  1.1044 +
  1.1045 +}
  1.1046 +
  1.1047 +using namespace TestTArray;
  1.1048 +
  1.1049 +int main(int argc, char **argv) {
  1.1050 +  int count = 1;
  1.1051 +  if (argc > 1)
  1.1052 +    count = atoi(argv[1]);
  1.1053 +
  1.1054 +  if (NS_FAILED(NS_InitXPCOM2(nullptr, nullptr, nullptr)))
  1.1055 +    return -1;
  1.1056 +
  1.1057 +  bool success = true;
  1.1058 +  while (count--) {
  1.1059 +    for (const Test* t = tests; t->name != nullptr; ++t) {
  1.1060 +      bool test_result = t->func();
  1.1061 +      printf("%25s : %s\n", t->name, test_result ? "SUCCESS" : "FAILURE");
  1.1062 +      if (!test_result)
  1.1063 +        success = false;
  1.1064 +    }
  1.1065 +  }
  1.1066 +  
  1.1067 +  NS_ShutdownXPCOM(nullptr);
  1.1068 +  return success ? 0 : -1;
  1.1069 +}

mercurial