Blame xpcom/tests/TestHarness.h

Packit f0b94e
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
Packit f0b94e
/* This Source Code Form is subject to the terms of the Mozilla Public
Packit f0b94e
 * License, v. 2.0. If a copy of the MPL was not distributed with this
Packit f0b94e
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
Packit f0b94e
Packit f0b94e
/*
Packit f0b94e
 * Test harness for XPCOM objects, providing a scoped XPCOM initializer,
Packit f0b94e
 * nsCOMPtr, nsRefPtr, do_CreateInstance, do_GetService, ns(Auto|C|)String,
Packit f0b94e
 * and stdio.h/stdlib.h.
Packit f0b94e
 */
Packit f0b94e
Packit f0b94e
#ifndef TestHarness_h__
Packit f0b94e
#define TestHarness_h__
Packit f0b94e
Packit f0b94e
#include "mozilla/ArrayUtils.h"
Packit f0b94e
#include "mozilla/Attributes.h"
Packit f0b94e
Packit f0b94e
#include "prenv.h"
Packit f0b94e
#include "nsComponentManagerUtils.h"
Packit f0b94e
#include "nsServiceManagerUtils.h"
Packit f0b94e
#include "nsCOMPtr.h"
Packit f0b94e
#include "nsAutoPtr.h"
Packit f0b94e
#include "nsString.h"
Packit f0b94e
#include "nsAppDirectoryServiceDefs.h"
Packit f0b94e
#include "nsDirectoryServiceDefs.h"
Packit f0b94e
#include "nsDirectoryServiceUtils.h"
Packit f0b94e
#include "nsIDirectoryService.h"
Packit f0b94e
#include "nsIFile.h"
Packit f0b94e
#include "nsIProperties.h"
Packit f0b94e
#include "nsIObserverService.h"
Packit f0b94e
#include "nsXULAppAPI.h"
Packit f0b94e
#include <stdio.h>
Packit f0b94e
#include <stdlib.h>
Packit f0b94e
#include <stdarg.h>
Packit f0b94e
Packit f0b94e
static uint32_t gFailCount = 0;
Packit f0b94e
Packit f0b94e
/**
Packit f0b94e
 * Prints the given failure message and arguments using printf, prepending
Packit f0b94e
 * "TEST-UNEXPECTED-FAIL " for the benefit of the test harness and
Packit f0b94e
 * appending "\n" to eliminate having to type it at each call site.
Packit f0b94e
 */
Packit f0b94e
MOZ_FORMAT_PRINTF(1, 2) void fail(const char* msg, ...)
Packit f0b94e
{
Packit f0b94e
  va_list ap;
Packit f0b94e
Packit f0b94e
  printf("TEST-UNEXPECTED-FAIL | ");
Packit f0b94e
Packit f0b94e
  va_start(ap, msg);
Packit f0b94e
  vprintf(msg, ap);
Packit f0b94e
  va_end(ap);
Packit f0b94e
Packit f0b94e
  putchar('\n');
Packit f0b94e
  ++gFailCount;
Packit f0b94e
}
Packit f0b94e
Packit f0b94e
/**
Packit f0b94e
 * Prints the given success message and arguments using printf, prepending
Packit f0b94e
 * "TEST-PASS " for the benefit of the test harness and
Packit f0b94e
 * appending "\n" to eliminate having to type it at each call site.
Packit f0b94e
 */
Packit f0b94e
MOZ_FORMAT_PRINTF(1, 2) void passed(const char* msg, ...)
Packit f0b94e
{
Packit f0b94e
  va_list ap;
Packit f0b94e
Packit f0b94e
  printf("TEST-PASS | ");
Packit f0b94e
Packit f0b94e
  va_start(ap, msg);
Packit f0b94e
  vprintf(msg, ap);
Packit f0b94e
  va_end(ap);
Packit f0b94e
Packit f0b94e
  putchar('\n');
Packit f0b94e
}
Packit f0b94e
Packit f0b94e
//-----------------------------------------------------------------------------
Packit f0b94e
Packit f0b94e
class ScopedXPCOM : public nsIDirectoryServiceProvider2
Packit f0b94e
{
Packit f0b94e
  public:
Packit f0b94e
    NS_DECL_ISUPPORTS
Packit f0b94e
Packit f0b94e
    explicit ScopedXPCOM(const char* testName,
Packit f0b94e
                         nsIDirectoryServiceProvider *dirSvcProvider = nullptr)
Packit f0b94e
    : mDirSvcProvider(dirSvcProvider)
Packit f0b94e
    {
Packit f0b94e
      mTestName = testName;
Packit f0b94e
      printf("Running %s tests...\n", mTestName);
Packit f0b94e
Packit f0b94e
      nsresult rv = NS_InitXPCOM2(&mServMgr, nullptr, this);
Packit f0b94e
      if (NS_FAILED(rv))
Packit f0b94e
      {
Packit f0b94e
        fail("NS_InitXPCOM2 returned failure code 0x%" PRIx32, static_cast<uint32_t>(rv));
Packit f0b94e
        mServMgr = nullptr;
Packit f0b94e
        return;
Packit f0b94e
      }
Packit f0b94e
    }
Packit f0b94e
Packit f0b94e
    ~ScopedXPCOM()
Packit f0b94e
    {
Packit f0b94e
      // If we created a profile directory, we need to remove it.
Packit f0b94e
      if (mProfD) {
Packit f0b94e
        nsCOMPtr<nsIObserverService> os =
Packit f0b94e
          do_GetService(NS_OBSERVERSERVICE_CONTRACTID);
Packit f0b94e
        MOZ_RELEASE_ASSERT(os);
Packit f0b94e
        MOZ_ALWAYS_SUCCEEDS(os->NotifyObservers(nullptr, "profile-change-net-teardown", nullptr));
Packit f0b94e
        MOZ_ALWAYS_SUCCEEDS(os->NotifyObservers(nullptr, "profile-change-teardown", nullptr));
Packit f0b94e
        MOZ_ALWAYS_SUCCEEDS(os->NotifyObservers(nullptr, "profile-before-change", nullptr));
Packit f0b94e
        MOZ_ALWAYS_SUCCEEDS(os->NotifyObservers(nullptr, "profile-before-change-qm", nullptr));
Packit f0b94e
        MOZ_ALWAYS_SUCCEEDS(os->NotifyObservers(nullptr, "profile-before-change-telemetry", nullptr));
Packit f0b94e
Packit f0b94e
        if (NS_FAILED(mProfD->Remove(true))) {
Packit f0b94e
          NS_WARNING("Problem removing profile directory");
Packit f0b94e
        }
Packit f0b94e
Packit f0b94e
        mProfD = nullptr;
Packit f0b94e
      }
Packit f0b94e
Packit f0b94e
      if (mServMgr)
Packit f0b94e
      {
Packit f0b94e
        NS_RELEASE(mServMgr);
Packit f0b94e
        nsresult rv = NS_ShutdownXPCOM(nullptr);
Packit f0b94e
        if (NS_FAILED(rv))
Packit f0b94e
        {
Packit f0b94e
          fail("XPCOM shutdown failed with code 0x%" PRIx32, static_cast<uint32_t>(rv));
Packit f0b94e
          exit(1);
Packit f0b94e
        }
Packit f0b94e
      }
Packit f0b94e
Packit f0b94e
      printf("Finished running %s tests.\n", mTestName);
Packit f0b94e
    }
Packit f0b94e
Packit f0b94e
    bool failed()
Packit f0b94e
    {
Packit f0b94e
      return mServMgr == nullptr;
Packit f0b94e
    }
Packit f0b94e
Packit f0b94e
    already_AddRefed<nsIFile> GetProfileDirectory()
Packit f0b94e
    {
Packit f0b94e
      if (mProfD) {
Packit f0b94e
        nsCOMPtr<nsIFile> copy = mProfD;
Packit f0b94e
        return copy.forget();
Packit f0b94e
      }
Packit f0b94e
Packit f0b94e
      // Create a unique temporary folder to use for this test.
Packit f0b94e
      // Note that runcppunittests.py will run tests with a temp
Packit f0b94e
      // directory as the cwd, so just put something under that.
Packit f0b94e
      nsCOMPtr<nsIFile> profD;
Packit f0b94e
      nsresult rv = NS_GetSpecialDirectory(NS_OS_CURRENT_PROCESS_DIR,
Packit f0b94e
                                           getter_AddRefs(profD));
Packit f0b94e
      NS_ENSURE_SUCCESS(rv, nullptr);
Packit f0b94e
Packit f0b94e
      rv = profD->Append(NS_LITERAL_STRING("cpp-unit-profd"));
Packit f0b94e
      NS_ENSURE_SUCCESS(rv, nullptr);
Packit f0b94e
Packit f0b94e
      rv = profD->CreateUnique(nsIFile::DIRECTORY_TYPE, 0755);
Packit f0b94e
      NS_ENSURE_SUCCESS(rv, nullptr);
Packit f0b94e
Packit f0b94e
      mProfD = profD;
Packit f0b94e
      return profD.forget();
Packit f0b94e
    }
Packit f0b94e
Packit f0b94e
    already_AddRefed<nsIFile> GetGREDirectory()
Packit f0b94e
    {
Packit f0b94e
      if (mGRED) {
Packit f0b94e
        nsCOMPtr<nsIFile> copy = mGRED;
Packit f0b94e
        return copy.forget();
Packit f0b94e
      }
Packit f0b94e
Packit f0b94e
      char* env = PR_GetEnv("MOZ_XRE_DIR");
Packit f0b94e
      nsCOMPtr<nsIFile> greD;
Packit f0b94e
      if (env) {
Packit f0b94e
        NS_NewLocalFile(NS_ConvertUTF8toUTF16(env), false,
Packit f0b94e
                        getter_AddRefs(greD));
Packit f0b94e
      }
Packit f0b94e
Packit f0b94e
      mGRED = greD;
Packit f0b94e
      return greD.forget();
Packit f0b94e
    }
Packit f0b94e
Packit f0b94e
    already_AddRefed<nsIFile> GetGREBinDirectory()
Packit f0b94e
    {
Packit f0b94e
      if (mGREBinD) {
Packit f0b94e
        nsCOMPtr<nsIFile> copy = mGREBinD;
Packit f0b94e
        return copy.forget();
Packit f0b94e
      }
Packit f0b94e
Packit f0b94e
      nsCOMPtr<nsIFile> greD = GetGREDirectory();
Packit f0b94e
      if (!greD) {
Packit f0b94e
        return greD.forget();
Packit f0b94e
      }
Packit f0b94e
      greD->Clone(getter_AddRefs(mGREBinD));
Packit f0b94e
Packit f0b94e
#ifdef XP_MACOSX
Packit f0b94e
      nsAutoCString leafName;
Packit f0b94e
      mGREBinD->GetNativeLeafName(leafName);
Packit f0b94e
      if (leafName.EqualsLiteral("Resources")) {
Packit f0b94e
        mGREBinD->SetNativeLeafName(NS_LITERAL_CSTRING("MacOS"));
Packit f0b94e
      }
Packit f0b94e
#endif
Packit f0b94e
Packit f0b94e
      nsCOMPtr<nsIFile> copy = mGREBinD;
Packit f0b94e
      return copy.forget();
Packit f0b94e
    }
Packit f0b94e
Packit f0b94e
    ////////////////////////////////////////////////////////////////////////////
Packit f0b94e
    //// nsIDirectoryServiceProvider
Packit f0b94e
Packit f0b94e
    NS_IMETHOD GetFile(const char *aProperty, bool *_persistent,
Packit f0b94e
                       nsIFile **_result) override
Packit f0b94e
    {
Packit f0b94e
      // If we were supplied a directory service provider, ask it first.
Packit f0b94e
      if (mDirSvcProvider &&
Packit f0b94e
          NS_SUCCEEDED(mDirSvcProvider->GetFile(aProperty, _persistent,
Packit f0b94e
                                                _result))) {
Packit f0b94e
        return NS_OK;
Packit f0b94e
      }
Packit f0b94e
Packit f0b94e
      // Otherwise, the test harness provides some directories automatically.
Packit f0b94e
      if (0 == strcmp(aProperty, NS_APP_USER_PROFILE_50_DIR) ||
Packit f0b94e
          0 == strcmp(aProperty, NS_APP_USER_PROFILE_LOCAL_50_DIR) ||
Packit f0b94e
          0 == strcmp(aProperty, NS_APP_PROFILE_LOCAL_DIR_STARTUP)) {
Packit f0b94e
        nsCOMPtr<nsIFile> profD = GetProfileDirectory();
Packit f0b94e
        NS_ENSURE_TRUE(profD, NS_ERROR_FAILURE);
Packit f0b94e
Packit f0b94e
        nsCOMPtr<nsIFile> clone;
Packit f0b94e
        nsresult rv = profD->Clone(getter_AddRefs(clone));
Packit f0b94e
        NS_ENSURE_SUCCESS(rv, rv);
Packit f0b94e
Packit f0b94e
        *_persistent = true;
Packit f0b94e
        clone.forget(_result);
Packit f0b94e
        return NS_OK;
Packit f0b94e
      } else if (0 == strcmp(aProperty, NS_GRE_DIR)) {
Packit f0b94e
        nsCOMPtr<nsIFile> greD = GetGREDirectory();
Packit f0b94e
        NS_ENSURE_TRUE(greD, NS_ERROR_FAILURE);
Packit f0b94e
Packit f0b94e
        *_persistent = true;
Packit f0b94e
        greD.forget(_result);
Packit f0b94e
        return NS_OK;
Packit f0b94e
      } else if (0 == strcmp(aProperty, NS_GRE_BIN_DIR)) {
Packit f0b94e
        nsCOMPtr<nsIFile> greBinD = GetGREBinDirectory();
Packit f0b94e
        NS_ENSURE_TRUE(greBinD, NS_ERROR_FAILURE);
Packit f0b94e
Packit f0b94e
        *_persistent = true;
Packit f0b94e
        greBinD.forget(_result);
Packit f0b94e
        return NS_OK;
Packit f0b94e
      }
Packit f0b94e
Packit f0b94e
      return NS_ERROR_FAILURE;
Packit f0b94e
    }
Packit f0b94e
Packit f0b94e
    ////////////////////////////////////////////////////////////////////////////
Packit f0b94e
    //// nsIDirectoryServiceProvider2
Packit f0b94e
Packit f0b94e
    NS_IMETHOD GetFiles(const char *aProperty, nsISimpleEnumerator **_enum) override
Packit f0b94e
    {
Packit f0b94e
      // If we were supplied a directory service provider, ask it first.
Packit f0b94e
      nsCOMPtr<nsIDirectoryServiceProvider2> provider =
Packit f0b94e
        do_QueryInterface(mDirSvcProvider);
Packit f0b94e
      if (provider && NS_SUCCEEDED(provider->GetFiles(aProperty, _enum))) {
Packit f0b94e
        return NS_OK;
Packit f0b94e
      }
Packit f0b94e
Packit f0b94e
     return NS_ERROR_FAILURE;
Packit f0b94e
   }
Packit f0b94e
Packit f0b94e
  private:
Packit f0b94e
    const char* mTestName;
Packit f0b94e
    nsIServiceManager* mServMgr;
Packit f0b94e
    nsCOMPtr<nsIDirectoryServiceProvider> mDirSvcProvider;
Packit f0b94e
    nsCOMPtr<nsIFile> mProfD;
Packit f0b94e
    nsCOMPtr<nsIFile> mGRED;
Packit f0b94e
    nsCOMPtr<nsIFile> mGREBinD;
Packit f0b94e
};
Packit f0b94e
Packit f0b94e
NS_IMPL_QUERY_INTERFACE(
Packit f0b94e
  ScopedXPCOM,
Packit f0b94e
  nsIDirectoryServiceProvider,
Packit f0b94e
  nsIDirectoryServiceProvider2
Packit f0b94e
)
Packit f0b94e
Packit f0b94e
NS_IMETHODIMP_(MozExternalRefCountType)
Packit f0b94e
ScopedXPCOM::AddRef()
Packit f0b94e
{
Packit f0b94e
  return 2;
Packit f0b94e
}
Packit f0b94e
Packit f0b94e
NS_IMETHODIMP_(MozExternalRefCountType)
Packit f0b94e
ScopedXPCOM::Release()
Packit f0b94e
{
Packit f0b94e
  return 1;
Packit f0b94e
}
Packit f0b94e
Packit f0b94e
#endif  // TestHarness_h__