Coverage Report

Created: 2018-09-25 14:53

/work/obj-fuzz/dist/include/testing/TestHarness.h
Line
Count
Source (jump to first uncovered line)
1
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
/* This Source Code Form is subject to the terms of the Mozilla Public
3
 * License, v. 2.0. If a copy of the MPL was not distributed with this
4
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5
6
/*
7
 * Test harness for XPCOM objects, providing a scoped XPCOM initializer,
8
 * nsCOMPtr, nsRefPtr, do_CreateInstance, do_GetService, ns(Auto|C|)String,
9
 * and stdio.h/stdlib.h.
10
 */
11
12
#ifndef TestHarness_h__
13
#define TestHarness_h__
14
15
#include "mozilla/ArrayUtils.h"
16
#include "mozilla/Attributes.h"
17
18
#include "prenv.h"
19
#include "nsComponentManagerUtils.h"
20
#include "nsServiceManagerUtils.h"
21
#include "nsCOMPtr.h"
22
#include "nsAutoPtr.h"
23
#include "nsString.h"
24
#include "nsAppDirectoryServiceDefs.h"
25
#include "nsDirectoryServiceDefs.h"
26
#include "nsDirectoryServiceUtils.h"
27
#include "nsIDirectoryService.h"
28
#include "nsIFile.h"
29
#include "nsIProperties.h"
30
#include "nsIObserverService.h"
31
#include "nsXULAppAPI.h"
32
#include <stdio.h>
33
#include <stdlib.h>
34
#include <stdarg.h>
35
36
static uint32_t gFailCount = 0;
37
38
/**
39
 * Prints the given failure message and arguments using printf, prepending
40
 * "TEST-UNEXPECTED-FAIL " for the benefit of the test harness and
41
 * appending "\n" to eliminate having to type it at each call site.
42
 */
43
MOZ_FORMAT_PRINTF(1, 2) void fail(const char* msg, ...)
44
0
{
45
0
  va_list ap;
46
0
47
0
  printf("TEST-UNEXPECTED-FAIL | ");
48
0
49
0
  va_start(ap, msg);
50
0
  vprintf(msg, ap);
51
0
  va_end(ap);
52
0
53
0
  putchar('\n');
54
0
  ++gFailCount;
55
0
}
56
57
/**
58
 * Prints the given success message and arguments using printf, prepending
59
 * "TEST-PASS " for the benefit of the test harness and
60
 * appending "\n" to eliminate having to type it at each call site.
61
 */
62
MOZ_FORMAT_PRINTF(1, 2) void passed(const char* msg, ...)
63
0
{
64
0
  va_list ap;
65
0
66
0
  printf("TEST-PASS | ");
67
0
68
0
  va_start(ap, msg);
69
0
  vprintf(msg, ap);
70
0
  va_end(ap);
71
0
72
0
  putchar('\n');
73
0
}
74
75
//-----------------------------------------------------------------------------
76
77
class ScopedXPCOM : public nsIDirectoryServiceProvider2
78
{
79
  public:
80
    NS_DECL_ISUPPORTS
81
82
    explicit ScopedXPCOM(const char* testName,
83
                         nsIDirectoryServiceProvider *dirSvcProvider = nullptr)
84
    : mServMgr(nullptr)
85
    , mDirSvcProvider(dirSvcProvider)
86
0
    {
87
0
      mTestName = testName;
88
0
      printf("Running %s tests...\n", mTestName);
89
0
90
0
      nsresult rv = NS_InitXPCOM2(&mServMgr, nullptr, this);
91
0
      if (NS_FAILED(rv))
92
0
      {
93
0
        fail("NS_InitXPCOM2 returned failure code 0x%" PRIx32, static_cast<uint32_t>(rv));
94
0
        mServMgr = nullptr;
95
0
        return;
96
0
      }
97
0
    }
98
99
    ~ScopedXPCOM()
100
0
    {
101
0
      // If we created a profile directory, we need to remove it.
102
0
      if (mProfD) {
103
0
        nsCOMPtr<nsIObserverService> os =
104
0
          do_GetService(NS_OBSERVERSERVICE_CONTRACTID);
105
0
        MOZ_RELEASE_ASSERT(os);
106
0
        MOZ_ALWAYS_SUCCEEDS(os->NotifyObservers(nullptr, "profile-change-net-teardown", nullptr));
107
0
        MOZ_ALWAYS_SUCCEEDS(os->NotifyObservers(nullptr, "profile-change-teardown", nullptr));
108
0
        MOZ_ALWAYS_SUCCEEDS(os->NotifyObservers(nullptr, "profile-before-change", nullptr));
109
0
        MOZ_ALWAYS_SUCCEEDS(os->NotifyObservers(nullptr, "profile-before-change-qm", nullptr));
110
0
        MOZ_ALWAYS_SUCCEEDS(os->NotifyObservers(nullptr, "profile-before-change-telemetry", nullptr));
111
0
112
0
        if (NS_FAILED(mProfD->Remove(true))) {
113
0
          NS_WARNING("Problem removing profile directory");
114
0
        }
115
0
116
0
        mProfD = nullptr;
117
0
      }
118
0
119
0
      if (mServMgr)
120
0
      {
121
0
        NS_RELEASE(mServMgr);
122
0
        nsresult rv = NS_ShutdownXPCOM(nullptr);
123
0
        if (NS_FAILED(rv))
124
0
        {
125
0
          fail("XPCOM shutdown failed with code 0x%" PRIx32, static_cast<uint32_t>(rv));
126
0
          exit(1);
127
0
        }
128
0
      }
129
0
130
0
      printf("Finished running %s tests.\n", mTestName);
131
0
    }
132
133
    bool failed()
134
0
    {
135
0
      return mServMgr == nullptr;
136
0
    }
137
138
    already_AddRefed<nsIFile> GetProfileDirectory()
139
0
    {
140
0
      if (mProfD) {
141
0
        nsCOMPtr<nsIFile> copy = mProfD;
142
0
        return copy.forget();
143
0
      }
144
0
145
0
      // Create a unique temporary folder to use for this test.
146
0
      // Note that runcppunittests.py will run tests with a temp
147
0
      // directory as the cwd, so just put something under that.
148
0
      nsCOMPtr<nsIFile> profD;
149
0
      nsresult rv = NS_GetSpecialDirectory(NS_OS_CURRENT_PROCESS_DIR,
150
0
                                           getter_AddRefs(profD));
151
0
      NS_ENSURE_SUCCESS(rv, nullptr);
152
0
153
0
      rv = profD->Append(NS_LITERAL_STRING("cpp-unit-profd"));
154
0
      NS_ENSURE_SUCCESS(rv, nullptr);
155
0
156
0
      rv = profD->CreateUnique(nsIFile::DIRECTORY_TYPE, 0755);
157
0
      NS_ENSURE_SUCCESS(rv, nullptr);
158
0
159
0
      mProfD = profD;
160
0
      return profD.forget();
161
0
    }
162
163
    already_AddRefed<nsIFile> GetGREDirectory()
164
0
    {
165
0
      if (mGRED) {
166
0
        nsCOMPtr<nsIFile> copy = mGRED;
167
0
        return copy.forget();
168
0
      }
169
0
170
0
      char* env = PR_GetEnv("MOZ_XRE_DIR");
171
0
      nsCOMPtr<nsIFile> greD;
172
0
      if (env) {
173
0
        NS_NewLocalFile(NS_ConvertUTF8toUTF16(env), false,
174
0
                        getter_AddRefs(greD));
175
0
      }
176
0
177
0
      mGRED = greD;
178
0
      return greD.forget();
179
0
    }
180
181
    already_AddRefed<nsIFile> GetGREBinDirectory()
182
0
    {
183
0
      if (mGREBinD) {
184
0
        nsCOMPtr<nsIFile> copy = mGREBinD;
185
0
        return copy.forget();
186
0
      }
187
0
188
0
      nsCOMPtr<nsIFile> greD = GetGREDirectory();
189
0
      if (!greD) {
190
0
        return greD.forget();
191
0
      }
192
0
      greD->Clone(getter_AddRefs(mGREBinD));
193
0
194
#ifdef XP_MACOSX
195
      nsAutoCString leafName;
196
      mGREBinD->GetNativeLeafName(leafName);
197
      if (leafName.EqualsLiteral("Resources")) {
198
        mGREBinD->SetNativeLeafName(NS_LITERAL_CSTRING("MacOS"));
199
      }
200
#endif
201
202
0
      nsCOMPtr<nsIFile> copy = mGREBinD;
203
0
      return copy.forget();
204
0
    }
205
206
    ////////////////////////////////////////////////////////////////////////////
207
    //// nsIDirectoryServiceProvider
208
209
    NS_IMETHOD GetFile(const char *aProperty, bool *_persistent,
210
                       nsIFile **_result) override
211
0
    {
212
0
      // If we were supplied a directory service provider, ask it first.
213
0
      if (mDirSvcProvider &&
214
0
          NS_SUCCEEDED(mDirSvcProvider->GetFile(aProperty, _persistent,
215
0
                                                _result))) {
216
0
        return NS_OK;
217
0
      }
218
0
219
0
      // Otherwise, the test harness provides some directories automatically.
220
0
      if (0 == strcmp(aProperty, NS_APP_USER_PROFILE_50_DIR) ||
221
0
          0 == strcmp(aProperty, NS_APP_USER_PROFILE_LOCAL_50_DIR) ||
222
0
          0 == strcmp(aProperty, NS_APP_PROFILE_LOCAL_DIR_STARTUP)) {
223
0
        nsCOMPtr<nsIFile> profD = GetProfileDirectory();
224
0
        NS_ENSURE_TRUE(profD, NS_ERROR_FAILURE);
225
0
226
0
        nsCOMPtr<nsIFile> clone;
227
0
        nsresult rv = profD->Clone(getter_AddRefs(clone));
228
0
        NS_ENSURE_SUCCESS(rv, rv);
229
0
230
0
        *_persistent = true;
231
0
        clone.forget(_result);
232
0
        return NS_OK;
233
0
      } else if (0 == strcmp(aProperty, NS_GRE_DIR)) {
234
0
        nsCOMPtr<nsIFile> greD = GetGREDirectory();
235
0
        NS_ENSURE_TRUE(greD, NS_ERROR_FAILURE);
236
0
237
0
        *_persistent = true;
238
0
        greD.forget(_result);
239
0
        return NS_OK;
240
0
      } else if (0 == strcmp(aProperty, NS_GRE_BIN_DIR)) {
241
0
        nsCOMPtr<nsIFile> greBinD = GetGREBinDirectory();
242
0
        NS_ENSURE_TRUE(greBinD, NS_ERROR_FAILURE);
243
0
244
0
        *_persistent = true;
245
0
        greBinD.forget(_result);
246
0
        return NS_OK;
247
0
      }
248
0
249
0
      return NS_ERROR_FAILURE;
250
0
    }
251
252
    ////////////////////////////////////////////////////////////////////////////
253
    //// nsIDirectoryServiceProvider2
254
255
    NS_IMETHOD GetFiles(const char *aProperty, nsISimpleEnumerator **_enum) override
256
0
    {
257
0
      // If we were supplied a directory service provider, ask it first.
258
0
      nsCOMPtr<nsIDirectoryServiceProvider2> provider =
259
0
        do_QueryInterface(mDirSvcProvider);
260
0
      if (provider && NS_SUCCEEDED(provider->GetFiles(aProperty, _enum))) {
261
0
        return NS_OK;
262
0
      }
263
0
264
0
     return NS_ERROR_FAILURE;
265
0
   }
266
267
  private:
268
    const char* mTestName;
269
    nsIServiceManager* mServMgr;
270
    nsCOMPtr<nsIDirectoryServiceProvider> mDirSvcProvider;
271
    nsCOMPtr<nsIFile> mProfD;
272
    nsCOMPtr<nsIFile> mGRED;
273
    nsCOMPtr<nsIFile> mGREBinD;
274
};
275
276
NS_IMPL_QUERY_INTERFACE(
277
  ScopedXPCOM,
278
  nsIDirectoryServiceProvider,
279
  nsIDirectoryServiceProvider2
280
)
281
282
NS_IMETHODIMP_(MozExternalRefCountType)
283
ScopedXPCOM::AddRef()
284
0
{
285
0
  return 2;
286
0
}
287
288
NS_IMETHODIMP_(MozExternalRefCountType)
289
ScopedXPCOM::Release()
290
0
{
291
0
  return 1;
292
0
}
293
294
#endif  // TestHarness_h__