Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/tools/fuzzing/interface/harness/FuzzerTestHarness.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 FuzzerTestHarness_h__
13
#define FuzzerTestHarness_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
namespace {
37
38
static uint32_t gFailCount = 0;
39
40
/**
41
 * Prints the given failure message and arguments using printf, prepending
42
 * "TEST-UNEXPECTED-FAIL " for the benefit of the test harness and
43
 * appending "\n" to eliminate having to type it at each call site.
44
 */
45
MOZ_FORMAT_PRINTF(1, 2) void fail(const char* msg, ...)
46
0
{
47
0
  va_list ap;
48
0
49
0
  printf("TEST-UNEXPECTED-FAIL | ");
50
0
51
0
  va_start(ap, msg);
52
0
  vprintf(msg, ap);
53
0
  va_end(ap);
54
0
55
0
  putchar('\n');
56
0
  ++gFailCount;
57
0
}
58
59
//-----------------------------------------------------------------------------
60
61
class ScopedXPCOM : public nsIDirectoryServiceProvider2
62
{
63
  public:
64
    NS_DECL_ISUPPORTS
65
66
    explicit ScopedXPCOM(const char* testName,
67
                         nsIDirectoryServiceProvider *dirSvcProvider = nullptr)
68
    : mDirSvcProvider(dirSvcProvider)
69
3
    {
70
3
      mTestName = testName;
71
3
      printf("Running %s tests...\n", mTestName);
72
3
73
3
      nsresult rv = NS_InitXPCOM2(&mServMgr, nullptr, this);
74
3
      if (NS_FAILED(rv))
75
3
      {
76
0
        fail("NS_InitXPCOM2 returned failure code 0x%" PRIx32, static_cast<uint32_t>(rv));
77
0
        mServMgr = nullptr;
78
0
        return;
79
0
      }
80
3
    }
81
82
    ~ScopedXPCOM()
83
0
    {
84
0
      // If we created a profile directory, we need to remove it.
85
0
      if (mProfD) {
86
0
        nsCOMPtr<nsIObserverService> os =
87
0
          do_GetService(NS_OBSERVERSERVICE_CONTRACTID);
88
0
        MOZ_ASSERT(os);
89
0
        if (os) {
90
0
          MOZ_ALWAYS_SUCCEEDS(os->NotifyObservers(nullptr, "profile-change-net-teardown", nullptr));
91
0
          MOZ_ALWAYS_SUCCEEDS(os->NotifyObservers(nullptr, "profile-change-teardown", nullptr));
92
0
          MOZ_ALWAYS_SUCCEEDS(os->NotifyObservers(nullptr, "profile-before-change", nullptr));
93
0
          MOZ_ALWAYS_SUCCEEDS(os->NotifyObservers(nullptr, "profile-before-change-qm", nullptr));
94
0
          MOZ_ALWAYS_SUCCEEDS(os->NotifyObservers(nullptr, "profile-before-change-telemetry", nullptr));
95
0
        }
96
0
97
0
        if (NS_FAILED(mProfD->Remove(true))) {
98
0
          NS_WARNING("Problem removing profile directory");
99
0
        }
100
0
101
0
        mProfD = nullptr;
102
0
      }
103
0
104
0
      if (mServMgr)
105
0
      {
106
0
        NS_RELEASE(mServMgr);
107
0
        nsresult rv = NS_ShutdownXPCOM(nullptr);
108
0
        if (NS_FAILED(rv))
109
0
        {
110
0
          fail("XPCOM shutdown failed with code 0x%" PRIx32, static_cast<uint32_t>(rv));
111
0
          exit(1);
112
0
        }
113
0
      }
114
0
115
0
      printf("Finished running %s tests.\n", mTestName);
116
0
    }
117
118
    already_AddRefed<nsIFile> GetProfileDirectory()
119
3
    {
120
3
      if (mProfD) {
121
0
        nsCOMPtr<nsIFile> copy = mProfD;
122
0
        return copy.forget();
123
0
      }
124
3
125
3
      // Create a unique temporary folder to use for this test.
126
3
      // Note that runcppunittests.py will run tests with a temp
127
3
      // directory as the cwd, so just put something under that.
128
3
      nsCOMPtr<nsIFile> profD;
129
3
      nsresult rv = NS_GetSpecialDirectory(NS_OS_CURRENT_PROCESS_DIR,
130
3
                                           getter_AddRefs(profD));
131
3
      NS_ENSURE_SUCCESS(rv, nullptr);
132
3
133
3
      rv = profD->Append(NS_LITERAL_STRING("cpp-unit-profd"));
134
3
      NS_ENSURE_SUCCESS(rv, nullptr);
135
3
136
3
      rv = profD->CreateUnique(nsIFile::DIRECTORY_TYPE, 0755);
137
3
      NS_ENSURE_SUCCESS(rv, nullptr);
138
3
139
3
      mProfD = profD;
140
3
      return profD.forget();
141
3
    }
142
143
    already_AddRefed<nsIFile> GetGREDirectory()
144
6
    {
145
6
      if (mGRED) {
146
0
        nsCOMPtr<nsIFile> copy = mGRED;
147
0
        return copy.forget();
148
0
      }
149
6
150
6
      char* env = PR_GetEnv("MOZ_XRE_DIR");
151
6
      nsCOMPtr<nsIFile> greD;
152
6
      if (env) {
153
0
        NS_NewLocalFile(NS_ConvertUTF8toUTF16(env), false,
154
0
                        getter_AddRefs(greD));
155
0
      }
156
6
157
6
      mGRED = greD;
158
6
      return greD.forget();
159
6
    }
160
161
    already_AddRefed<nsIFile> GetGREBinDirectory()
162
3
    {
163
3
      if (mGREBinD) {
164
0
        nsCOMPtr<nsIFile> copy = mGREBinD;
165
0
        return copy.forget();
166
0
      }
167
3
168
3
      nsCOMPtr<nsIFile> greD = GetGREDirectory();
169
3
      if (!greD) {
170
3
        return greD.forget();
171
3
      }
172
0
      greD->Clone(getter_AddRefs(mGREBinD));
173
0
174
#ifdef XP_MACOSX
175
      nsAutoCString leafName;
176
      mGREBinD->GetNativeLeafName(leafName);
177
      if (leafName.EqualsLiteral("Resources")) {
178
        mGREBinD->SetNativeLeafName(NS_LITERAL_CSTRING("MacOS"));
179
      }
180
#endif
181
182
0
      nsCOMPtr<nsIFile> copy = mGREBinD;
183
0
      return copy.forget();
184
0
    }
185
186
    ////////////////////////////////////////////////////////////////////////////
187
    //// nsIDirectoryServiceProvider
188
189
    NS_IMETHODIMP GetFile(const char *aProperty, bool *_persistent,
190
                          nsIFile **_result) override
191
36
    {
192
36
      // If we were supplied a directory service provider, ask it first.
193
36
      if (mDirSvcProvider &&
194
36
          NS_SUCCEEDED(mDirSvcProvider->GetFile(aProperty, _persistent,
195
36
                                                _result))) {
196
0
        return NS_OK;
197
0
      }
198
36
199
36
      // Otherwise, the test harness provides some directories automatically.
200
36
      if (0 == strcmp(aProperty, NS_APP_USER_PROFILE_50_DIR) ||
201
36
          0 == strcmp(aProperty, NS_APP_USER_PROFILE_LOCAL_50_DIR) ||
202
36
          0 == strcmp(aProperty, NS_APP_PROFILE_LOCAL_DIR_STARTUP)) {
203
3
        nsCOMPtr<nsIFile> profD = GetProfileDirectory();
204
3
        NS_ENSURE_TRUE(profD, NS_ERROR_FAILURE);
205
3
206
3
        nsCOMPtr<nsIFile> clone;
207
3
        nsresult rv = profD->Clone(getter_AddRefs(clone));
208
3
        NS_ENSURE_SUCCESS(rv, rv);
209
3
210
3
        *_persistent = true;
211
3
        clone.forget(_result);
212
3
        return NS_OK;
213
33
      } else if (0 == strcmp(aProperty, NS_GRE_DIR)) {
214
3
        nsCOMPtr<nsIFile> greD = GetGREDirectory();
215
3
        NS_ENSURE_TRUE(greD, NS_ERROR_FAILURE);
216
3
217
3
        *_persistent = true;
218
0
        greD.forget(_result);
219
0
        return NS_OK;
220
30
      } else if (0 == strcmp(aProperty, NS_GRE_BIN_DIR)) {
221
3
        nsCOMPtr<nsIFile> greBinD = GetGREBinDirectory();
222
3
        NS_ENSURE_TRUE(greBinD, NS_ERROR_FAILURE);
223
3
224
3
        *_persistent = true;
225
0
        greBinD.forget(_result);
226
0
        return NS_OK;
227
27
      }
228
27
229
27
      return NS_ERROR_FAILURE;
230
27
    }
231
232
    ////////////////////////////////////////////////////////////////////////////
233
    //// nsIDirectoryServiceProvider2
234
235
    NS_IMETHODIMP GetFiles(const char *aProperty, nsISimpleEnumerator **_enum) override
236
3
    {
237
3
      // If we were supplied a directory service provider, ask it first.
238
3
      nsCOMPtr<nsIDirectoryServiceProvider2> provider =
239
3
        do_QueryInterface(mDirSvcProvider);
240
3
      if (provider && NS_SUCCEEDED(provider->GetFiles(aProperty, _enum))) {
241
0
        return NS_OK;
242
0
      }
243
3
244
3
     return NS_ERROR_FAILURE;
245
3
   }
246
247
  private:
248
    const char* mTestName;
249
    nsIServiceManager* mServMgr;
250
    nsCOMPtr<nsIDirectoryServiceProvider> mDirSvcProvider;
251
    nsCOMPtr<nsIFile> mProfD;
252
    nsCOMPtr<nsIFile> mGRED;
253
    nsCOMPtr<nsIFile> mGREBinD;
254
};
255
256
NS_IMPL_QUERY_INTERFACE(
257
  ScopedXPCOM,
258
  nsIDirectoryServiceProvider,
259
  nsIDirectoryServiceProvider2
260
)
261
262
NS_IMETHODIMP_(MozExternalRefCountType)
263
ScopedXPCOM::AddRef()
264
6
{
265
6
  return 2;
266
6
}
267
268
NS_IMETHODIMP_(MozExternalRefCountType)
269
ScopedXPCOM::Release()
270
3
{
271
3
  return 1;
272
3
}
273
274
} // namespace
275
276
#endif  // FuzzerTestHarness_h__