Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/toolkit/components/url-classifier/tests/gtest/Common.cpp
Line
Count
Source (jump to first uncovered line)
1
#include "Common.h"
2
#include "HashStore.h"
3
#include "Classifier.h"
4
#include "nsAppDirectoryServiceDefs.h"
5
#include "nsTArray.h"
6
#include "nsIThread.h"
7
#include "nsThreadUtils.h"
8
#include "nsUrlClassifierUtils.h"
9
10
using namespace mozilla;
11
using namespace mozilla::safebrowsing;
12
13
0
#define GTEST_SAFEBROWSING_DIR NS_LITERAL_CSTRING("safebrowsing")
14
0
#define GTEST_TABLE NS_LITERAL_CSTRING("gtest-malware-proto")
15
16
template<typename Function>
17
0
void RunTestInNewThread(Function&& aFunction) {
18
0
  nsCOMPtr<nsIRunnable> r = NS_NewRunnableFunction(
19
0
    "RunTestInNewThread", std::forward<Function>(aFunction));
20
0
  nsCOMPtr<nsIThread> testingThread;
21
0
  nsresult rv =
22
0
    NS_NewNamedThread("Testing Thread", getter_AddRefs(testingThread), r);
23
0
  ASSERT_EQ(rv, NS_OK);
24
0
  testingThread->Shutdown();
25
0
}
Unexecuted instantiation: Unified_cpp_tests_gtest0.cpp:void RunTestInNewThread<testOpenLookupCache()::$_7>(testOpenLookupCache()::$_7&&)
Unexecuted instantiation: Unified_cpp_tests_gtest0.cpp:void RunTestInNewThread<TestHasPrefix(nsTString<char> const&, bool, bool)::$_3>(TestHasPrefix(nsTString<char> const&, bool, bool)::$_3&&)
Unexecuted instantiation: Unified_cpp_tests_gtest0.cpp:void RunTestInNewThread<UrlClassifierPerProviderDirectory_LookupCache_Test::TestBody()::$_4>(UrlClassifierPerProviderDirectory_LookupCache_Test::TestBody()::$_4&&)
Unexecuted instantiation: Unified_cpp_tests_gtest0.cpp:void RunTestInNewThread<UrlClassifierPerProviderDirectory_HashStore_Test::TestBody()::$_5>(UrlClassifierPerProviderDirectory_HashStore_Test::TestBody()::$_5&&)
26
27
nsresult SyncApplyUpdates(RefPtr<Classifier> aClassifier,
28
                          TableUpdateArray& aUpdates)
29
0
{
30
0
  // We need to spin a new thread specifically because the callback
31
0
  // will be on the caller thread. If we call Classifier::AsyncApplyUpdates
32
0
  // and wait on the same thread, this function will never return.
33
0
34
0
  nsresult ret = NS_ERROR_FAILURE;
35
0
  bool done = false;
36
0
  auto onUpdateComplete = [&done, &ret](nsresult rv) {
37
0
    // We are on the "ApplyUpdate" thread. Post an event to main thread
38
0
    // so that we can avoid busy waiting on the main thread.
39
0
    nsCOMPtr<nsIRunnable> r =
40
0
      NS_NewRunnableFunction("SyncApplyUpdates", [&done, &ret, rv] {
41
0
        ret = rv;
42
0
        done = true;
43
0
      });
44
0
    NS_DispatchToMainThread(r);
45
0
  };
46
0
47
0
  nsCOMPtr<nsIRunnable> r = NS_NewRunnableFunction("SyncApplyUpdates", [&]() {
48
0
    nsresult rv = aClassifier->AsyncApplyUpdates(aUpdates, onUpdateComplete);
49
0
    if (NS_FAILED(rv)) {
50
0
      onUpdateComplete(rv);
51
0
    }
52
0
  });
53
0
54
0
  nsCOMPtr<nsIThread> testingThread;
55
0
  NS_NewNamedThread("ApplyUpdates", getter_AddRefs(testingThread));
56
0
  if (!testingThread) {
57
0
    return NS_ERROR_FAILURE;
58
0
  }
59
0
60
0
  testingThread->Dispatch(r, NS_DISPATCH_NORMAL);
61
0
62
0
  // NS_NewCheckSummedOutputStream in HashStore::WriteFile
63
0
  // will synchronously init NS_CRYPTO_HASH_CONTRACTID on
64
0
  // the main thread. As a result we have to keep processing
65
0
  // pending event until |done| becomes true. If there's no
66
0
  // more pending event, what we only can do is wait.
67
0
  MOZ_ALWAYS_TRUE(SpinEventLoopUntil([&]() { return done; }));
68
0
69
0
  return ret;
70
0
}
71
72
already_AddRefed<nsIFile>
73
GetFile(const nsTArray<nsString>& path)
74
0
{
75
0
  nsCOMPtr<nsIFile> file;
76
0
  nsresult rv = NS_GetSpecialDirectory(NS_APP_USER_PROFILE_50_DIR, getter_AddRefs(file));
77
0
  if (NS_WARN_IF(NS_FAILED(rv))) {
78
0
    return nullptr;
79
0
  }
80
0
81
0
  for (uint32_t i = 0; i < path.Length(); i++) {
82
0
    file->Append(path[i]);
83
0
  }
84
0
  return file.forget();
85
0
}
86
87
void ApplyUpdate(TableUpdateArray& updates)
88
0
{
89
0
  nsCOMPtr<nsIFile> file;
90
0
  NS_GetSpecialDirectory(NS_APP_USER_PROFILE_50_DIR, getter_AddRefs(file));
91
0
92
0
  RefPtr<Classifier> classifier = new Classifier();
93
0
  classifier->Open(*file);
94
0
95
0
  {
96
0
    // Force nsIUrlClassifierUtils loading on main thread
97
0
    // because nsIUrlClassifierDBService will not run in advance
98
0
    // in gtest.
99
0
    nsresult rv;
100
0
    nsCOMPtr<nsIUrlClassifierUtils> dummy =
101
0
      do_GetService(NS_URLCLASSIFIERUTILS_CONTRACTID, &rv);
102
0
      ASSERT_TRUE(NS_SUCCEEDED(rv));
103
0
  }
104
0
105
0
  SyncApplyUpdates(classifier, updates);
106
0
}
107
108
void ApplyUpdate(TableUpdate* update)
109
0
{
110
0
  TableUpdateArray updates = { update };
111
0
  ApplyUpdate(updates);
112
0
}
113
114
void
115
PrefixArrayToPrefixStringMap(const nsTArray<nsCString>& prefixArray,
116
                             PrefixStringMap& out)
117
0
{
118
0
  out.Clear();
119
0
120
0
  for (uint32_t i = 0; i < prefixArray.Length(); i++) {
121
0
    const nsCString& prefix = prefixArray[i];
122
0
    nsCString* prefixString = out.LookupOrAdd(prefix.Length());
123
0
    prefixString->Append(prefix.BeginReading(), prefix.Length());
124
0
  }
125
0
}
126
127
nsresult
128
PrefixArrayToAddPrefixArrayV2(const nsTArray<nsCString>& prefixArray,
129
                              AddPrefixArray& out)
130
0
{
131
0
  out.Clear();
132
0
133
0
  for (size_t i = 0; i < prefixArray.Length(); i++) {
134
0
    // Create prefix hash from string
135
0
    Prefix hash;
136
0
    static_assert(sizeof(hash.buf) == PREFIX_SIZE, "Prefix must be 4 bytes length");
137
0
    memcpy(hash.buf, prefixArray[i].BeginReading(), PREFIX_SIZE);
138
0
139
0
    AddPrefix *add = out.AppendElement(fallible);
140
0
    if (!add) {
141
0
      return NS_ERROR_OUT_OF_MEMORY;
142
0
    }
143
0
144
0
    add->addChunk = i;
145
0
    add->prefix = hash;
146
0
  }
147
0
148
0
  return NS_OK;
149
0
}
150
151
nsCString
152
GeneratePrefix(const nsCString& aFragment, uint8_t aLength)
153
0
{
154
0
  Completion complete;
155
0
  complete.FromPlaintext(aFragment);
156
0
157
0
  nsCString hash;
158
0
  hash.Assign((const char *)complete.buf, aLength);
159
0
  return hash;
160
0
}
161
162
static nsresult
163
BuildCache(LookupCacheV2* cache, const _PrefixArray& prefixArray)
164
0
{
165
0
  AddPrefixArray prefixes;
166
0
  AddCompleteArray completions;
167
0
  nsresult rv = PrefixArrayToAddPrefixArrayV2(prefixArray, prefixes);
168
0
  if (NS_FAILED(rv)) {
169
0
    return rv;
170
0
  }
171
0
172
0
  EntrySort(prefixes);
173
0
  return cache->Build(prefixes, completions);
174
0
}
175
176
static nsresult
177
BuildCache(LookupCacheV4* cache, const _PrefixArray& prefixArray)
178
0
{
179
0
  PrefixStringMap map;
180
0
  PrefixArrayToPrefixStringMap(prefixArray, map);
181
0
  return cache->Build(map);
182
0
}
183
184
template<typename T>
185
RefPtr<T>
186
SetupLookupCache(const _PrefixArray& prefixArray)
187
0
{
188
0
  nsCOMPtr<nsIFile> file;
189
0
  NS_GetSpecialDirectory(NS_APP_USER_PROFILE_50_DIR, getter_AddRefs(file));
190
0
191
0
  file->AppendNative(GTEST_SAFEBROWSING_DIR);
192
0
193
0
  RefPtr<T> cache = new T(GTEST_TABLE, EmptyCString(), file);
194
0
  nsresult rv = cache->Init();
195
0
  EXPECT_EQ(rv, NS_OK);
196
0
197
0
  rv = BuildCache(cache, prefixArray);
198
0
  EXPECT_EQ(rv, NS_OK);
199
0
200
0
  return cache;
201
0
}
Unexecuted instantiation: RefPtr<mozilla::safebrowsing::LookupCacheV2> SetupLookupCache<mozilla::safebrowsing::LookupCacheV2>(nsTArray<nsTString<char> > const&)
Unexecuted instantiation: RefPtr<mozilla::safebrowsing::LookupCacheV4> SetupLookupCache<mozilla::safebrowsing::LookupCacheV4>(nsTArray<nsTString<char> > const&)