зеркало из https://github.com/mozilla/gecko-dev.git
merge mozilla-inbound to mozilla-central a=merge
This commit is contained in:
Коммит
92cce75ada
|
@ -32,6 +32,8 @@
|
|||
#include "AudioOutputObserver.h"
|
||||
#endif
|
||||
|
||||
#include "webaudio/blink/HRTFDatabaseLoader.h"
|
||||
|
||||
using namespace mozilla::layers;
|
||||
using namespace mozilla::dom;
|
||||
using namespace mozilla::gfx;
|
||||
|
@ -2911,6 +2913,15 @@ MediaStreamGraphImpl::CollectReports(nsIHandleReportCallback* aHandleReport,
|
|||
|
||||
}
|
||||
|
||||
size_t hrtfLoaders = WebCore::HRTFDatabaseLoader::sizeOfLoaders(MallocSizeOf);
|
||||
if (hrtfLoaders) {
|
||||
|
||||
REPORT(NS_LITERAL_CSTRING(
|
||||
"explicit/webaudio/audio-node/PannerNode/hrtf-databases"),
|
||||
hrtfLoaders,
|
||||
"Memory used by PannerNode databases (Web Audio).");
|
||||
}
|
||||
|
||||
#undef REPORT
|
||||
|
||||
return NS_OK;
|
||||
|
|
|
@ -37,6 +37,11 @@ namespace WebCore {
|
|||
nsTHashtable<HRTFDatabaseLoader::LoaderByRateEntry>*
|
||||
HRTFDatabaseLoader::s_loaderMap = nullptr;
|
||||
|
||||
size_t HRTFDatabaseLoader::sizeOfLoaders(mozilla::MallocSizeOf aMallocSizeOf)
|
||||
{
|
||||
return s_loaderMap ? s_loaderMap->SizeOfIncludingThis(aMallocSizeOf) : 0;
|
||||
}
|
||||
|
||||
TemporaryRef<HRTFDatabaseLoader> HRTFDatabaseLoader::createAndLoadAsynchronouslyIfNecessary(float sampleRate)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
|
|
@ -94,13 +94,16 @@ public:
|
|||
// Called in asynchronous loading thread.
|
||||
void load();
|
||||
|
||||
size_t sizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
|
||||
// Sums the size of all cached database loaders.
|
||||
static size_t sizeOfLoaders(mozilla::MallocSizeOf aMallocSizeOf);
|
||||
|
||||
private:
|
||||
// Both constructor and destructor must be called from the main thread.
|
||||
explicit HRTFDatabaseLoader(float sampleRate);
|
||||
~HRTFDatabaseLoader();
|
||||
|
||||
|
||||
size_t sizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
|
||||
|
||||
void ProxyRelease(); // any thread
|
||||
void MainThreadRelease(); // main thread only
|
||||
class ProxyReleaseEvent;
|
||||
|
@ -117,6 +120,12 @@ private:
|
|||
, mLoader() // so PutEntry() will zero-initialize
|
||||
{
|
||||
}
|
||||
|
||||
size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
|
||||
{
|
||||
return mLoader ? mLoader->sizeOfIncludingThis(aMallocSizeOf) : 0;
|
||||
}
|
||||
|
||||
HRTFDatabaseLoader* mLoader;
|
||||
};
|
||||
|
||||
|
|
|
@ -74,10 +74,7 @@ size_t HRTFPanner::sizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) cons
|
|||
{
|
||||
size_t amount = aMallocSizeOf(this);
|
||||
|
||||
if (m_databaseLoader) {
|
||||
m_databaseLoader->sizeOfIncludingThis(aMallocSizeOf);
|
||||
}
|
||||
|
||||
// NB: m_databaseLoader can be shared, so it is not measured here
|
||||
amount += m_convolverL1.sizeOfExcludingThis(aMallocSizeOf);
|
||||
amount += m_convolverR1.sizeOfExcludingThis(aMallocSizeOf);
|
||||
amount += m_convolverL2.sizeOfExcludingThis(aMallocSizeOf);
|
||||
|
|
|
@ -4,6 +4,7 @@ support-files =
|
|||
head.js
|
||||
constraints.js
|
||||
mediaStreamPlayback.js
|
||||
nonTrickleIce.js
|
||||
pc.js
|
||||
templates.js
|
||||
NetworkPreparationChromeScript.js
|
||||
|
@ -91,6 +92,12 @@ skip-if = buildapp == 'b2g' || os == 'android' # bug 1043403
|
|||
skip-if = toolkit == 'gonk' # b2g (Bug 1059867)
|
||||
[test_peerConnection_errorCallbacks.html]
|
||||
skip-if = toolkit == 'gonk' # b2g (Bug 1059867)
|
||||
[test_peerConnection_noTrickleAnswer.html]
|
||||
skip-if = toolkit == 'gonk' # b2g (Bug 1059867)
|
||||
[test_peerConnection_noTrickleOffer.html]
|
||||
skip-if = toolkit == 'gonk' # b2g (Bug 1059867)
|
||||
[test_peerConnection_noTrickleOfferAnswer.html]
|
||||
skip-if = toolkit == 'gonk' # b2g (Bug 1059867)
|
||||
[test_peerConnection_offerRequiresReceiveAudio.html]
|
||||
skip-if = toolkit == 'gonk' # b2g(Bug 960442, video support for WebRTC is disabled on b2g)
|
||||
[test_peerConnection_offerRequiresReceiveVideo.html]
|
||||
|
|
|
@ -0,0 +1,130 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
function makeOffererNonTrickle(chain) {
|
||||
chain.replace('PC_LOCAL_SETUP_ICE_HANDLER', [
|
||||
['PC_LOCAL_SETUP_NOTRICKLE_ICE_HANDLER',
|
||||
function (test) {
|
||||
test.pcLocalWaitingForEndOfTrickleIce = false;
|
||||
// We need to install this callback before calling setLocalDescription
|
||||
// otherwise we might miss callbacks
|
||||
test.pcLocal.setupIceCandidateHandler(test, function () {
|
||||
// We ignore ICE candidates because we want the full offer
|
||||
} , function (label) {
|
||||
if (test.pcLocalWaitingForEndOfTrickleIce) {
|
||||
// This callback is needed for slow environments where ICE
|
||||
// trickling has not finished before the other side needs the
|
||||
// full SDP. In this case, this call to test.next() will complete
|
||||
// the PC_REMOTE_WAIT_FOR_OFFER step (see below).
|
||||
info("Looks like we were still waiting for Trickle to finish");
|
||||
// TODO replace this with a Promise
|
||||
test.next();
|
||||
}
|
||||
});
|
||||
// We can't wait for trickle to finish here as it will only start once
|
||||
// we have called setLocalDescription in the next step
|
||||
test.next();
|
||||
}
|
||||
]
|
||||
]);
|
||||
chain.replace('PC_REMOTE_GET_OFFER', [
|
||||
['PC_REMOTE_WAIT_FOR_OFFER',
|
||||
function (test) {
|
||||
if (test.pcLocal.endOfTrickleIce) {
|
||||
info("Trickle ICE finished already");
|
||||
test.next();
|
||||
} else {
|
||||
info("Waiting for trickle ICE to finish");
|
||||
test.pcLocalWaitingForEndOfTrickleIce = true;
|
||||
// In this case we rely on the callback from
|
||||
// PC_LOCAL_SETUP_NOTRICKLE_ICE_HANDLER above to proceed to the next
|
||||
// step once trickle is finished.
|
||||
}
|
||||
}
|
||||
],
|
||||
['PC_REMOTE_GET_FULL_OFFER',
|
||||
function (test) {
|
||||
test._local_offer = test.pcLocal.localDescription;
|
||||
test._offer_constraints = test.pcLocal.constraints;
|
||||
test._offer_options = test.pcLocal.offerOptions;
|
||||
test.next();
|
||||
}
|
||||
]
|
||||
]);
|
||||
chain.insertAfter('PC_REMOTE_SANE_REMOTE_SDP', [
|
||||
['PC_REMOTE_REQUIRE_REMOTE_SDP_CANDIDATES',
|
||||
function (test) {
|
||||
info("test.pcLocal.localDescription.sdp: " + JSON.stringify(test.pcLocal.localDescription.sdp));
|
||||
info("test._local_offer.sdp" + JSON.stringify(test._local_offer.sdp));
|
||||
ok(!test.localRequiresTrickleIce, "Local does NOT require trickle");
|
||||
ok(test._local_offer.sdp.contains("a=candidate"), "offer has ICE candidates")
|
||||
// TODO check for a=end-of-candidates once implemented
|
||||
test.next();
|
||||
}
|
||||
]
|
||||
]);
|
||||
}
|
||||
|
||||
function makeAnswererNonTrickle(chain) {
|
||||
chain.replace('PC_REMOTE_SETUP_ICE_HANDLER', [
|
||||
['PC_REMOTE_SETUP_NOTRICKLE_ICE_HANDLER',
|
||||
function (test) {
|
||||
test.pcRemoteWaitingForEndOfTrickleIce = false;
|
||||
// We need to install this callback before calling setLocalDescription
|
||||
// otherwise we might miss callbacks
|
||||
test.pcRemote.setupIceCandidateHandler(test, function () {
|
||||
// We ignore ICE candidates because we want the full answer
|
||||
}, function (label) {
|
||||
if (test.pcRemoteWaitingForEndOfTrickleIce) {
|
||||
// This callback is needed for slow environments where ICE
|
||||
// trickling has not finished before the other side needs the
|
||||
// full SDP. In this case this callback will call the step after
|
||||
// PC_LOCAL_WAIT_FOR_ANSWER
|
||||
info("Looks like we were still waiting for Trickle to finish");
|
||||
// TODO replace this with a Promise
|
||||
test.next();
|
||||
}
|
||||
});
|
||||
// We can't wait for trickle to finish here as it will only start once
|
||||
// we have called setLocalDescription in the next step
|
||||
test.next();
|
||||
}
|
||||
]
|
||||
]);
|
||||
chain.replace('PC_LOCAL_GET_ANSWER', [
|
||||
['PC_LOCAL_WAIT_FOR_ANSWER',
|
||||
function (test) {
|
||||
if (test.pcRemote.endOfTrickleIce) {
|
||||
info("Trickle ICE finished already");
|
||||
test.next();
|
||||
} else {
|
||||
info("Waiting for trickle ICE to finish");
|
||||
test.pcRemoteWaitingForEndOfTrickleIce = true;
|
||||
// In this case we rely on the callback from
|
||||
// PC_REMOTE_SETUP_NOTRICKLE_ICE_HANDLER above to proceed to the next
|
||||
// step once trickle is finished.
|
||||
}
|
||||
}
|
||||
],
|
||||
['PC_LOCAL_GET_FULL_ANSWER',
|
||||
function (test) {
|
||||
test._remote_answer = test.pcRemote.localDescription;
|
||||
test._answer_constraints = test.pcRemote.constraints;
|
||||
test.next();
|
||||
}
|
||||
]
|
||||
]);
|
||||
chain.insertAfter('PC_LOCAL_SANE_REMOTE_SDP', [
|
||||
['PC_LOCAL_REQUIRE_REMOTE_SDP_CANDIDATES',
|
||||
function (test) {
|
||||
info("test.pcRemote.localDescription.sdp: " + JSON.stringify(test.pcRemote.localDescription.sdp));
|
||||
info("test._remote_answer.sdp" + JSON.stringify(test._remote_answer.sdp));
|
||||
ok(!test.remoteRequiresTrickleIce, "Remote does NOT require trickle");
|
||||
ok(test._remote_answer.sdp.contains("a=candidate"), "answer has ICE candidates")
|
||||
// TODO check for a=end-of-candidates once implemented
|
||||
test.next();
|
||||
}
|
||||
]
|
||||
]);
|
||||
}
|
|
@ -224,6 +224,20 @@ CommandChain.prototype = {
|
|||
return null;
|
||||
},
|
||||
|
||||
/**
|
||||
* Replaces a single command.
|
||||
*
|
||||
* @param {string} id
|
||||
* Identifier of the command to be replaced
|
||||
* @param {Array[]} commands
|
||||
* List of commands
|
||||
* @returns {object[]} Removed commands
|
||||
*/
|
||||
replace : function (id, commands) {
|
||||
this.insertBefore(id, commands);
|
||||
return this.remove(id);
|
||||
},
|
||||
|
||||
/**
|
||||
* Replaces all commands after the specified one.
|
||||
*
|
||||
|
@ -2085,18 +2099,22 @@ PeerConnectionWrapper.prototype = {
|
|||
* A PeerConnectionTest object to which the ice candidates gets
|
||||
* forwarded.
|
||||
*/
|
||||
setupIceCandidateHandler : function PCW_setupIceCandidateHandler(test) {
|
||||
setupIceCandidateHandler : function
|
||||
PCW_setupIceCandidateHandler(test, candidateHandler, endHandler) {
|
||||
var self = this;
|
||||
self._local_ice_candidates = [];
|
||||
self._remote_ice_candidates = [];
|
||||
self._ice_candidates_to_add = [];
|
||||
|
||||
candidateHandler = candidateHandler || test.iceCandidateHandler.bind(test);
|
||||
endHandler = endHandler || test.signalEndOfTrickleIce.bind(test);
|
||||
|
||||
function iceCandidateCallback (anEvent) {
|
||||
info(self.label + ": received iceCandidateEvent");
|
||||
if (!anEvent.candidate) {
|
||||
info(self.label + ": received end of trickle ICE event");
|
||||
self.endOfTrickleIce = true;
|
||||
test.signalEndOfTrickleIce(self.label);
|
||||
endHandler(self.label);
|
||||
} else {
|
||||
if (self.endOfTrickleIce) {
|
||||
ok(false, "received ICE candidate after end of trickle");
|
||||
|
@ -2107,7 +2125,7 @@ PeerConnectionWrapper.prototype = {
|
|||
ok(anEvent.candidate.sdpMid.length === 0, "SDP MID has length zero");
|
||||
ok(typeof anEvent.candidate.sdpMLineIndex === 'number', "SDP MLine Index needs to exist");
|
||||
self._local_ice_candidates.push(anEvent.candidate);
|
||||
test.iceCandidateHandler(self.label, anEvent.candidate);
|
||||
candidateHandler(self.label, anEvent.candidate);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript" src="head.js"></script>
|
||||
<script type="application/javascript" src="mediaStreamPlayback.js"></script>
|
||||
<script type="application/javascript" src="nonTrickleIce.js"></script>
|
||||
<script type="application/javascript" src="pc.js"></script>
|
||||
<script type="application/javascript" src="templates.js"></script>
|
||||
<script type="application/javascript" src="turnConfig.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<pre id="test">
|
||||
<script type="application/javascript">
|
||||
createHTML({
|
||||
bug: "1060102",
|
||||
title: "Basic audio only SDP answer without trickle ICE"
|
||||
});
|
||||
|
||||
var test;
|
||||
runNetworkTest(function (options) {
|
||||
test = new PeerConnectionTest(options);
|
||||
makeAnswererNonTrickle(test.chain);
|
||||
test.setMediaConstraints([{audio: true}], [{audio: true}]);
|
||||
test.run();
|
||||
});
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,31 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript" src="head.js"></script>
|
||||
<script type="application/javascript" src="mediaStreamPlayback.js"></script>
|
||||
<script type="application/javascript" src="nonTrickleIce.js"></script>
|
||||
<script type="application/javascript" src="pc.js"></script>
|
||||
<script type="application/javascript" src="templates.js"></script>
|
||||
<script type="application/javascript" src="turnConfig.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<pre id="test">
|
||||
<script type="application/javascript">
|
||||
createHTML({
|
||||
bug: "1060102",
|
||||
title: "Basic audio only SDP offer without trickle ICE"
|
||||
});
|
||||
|
||||
var test;
|
||||
runNetworkTest(function (options) {
|
||||
test = new PeerConnectionTest(options);
|
||||
makeOffererNonTrickle(test.chain);
|
||||
test.setMediaConstraints([{audio: true}], [{audio: true}]);
|
||||
test.run();
|
||||
});
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,32 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript" src="head.js"></script>
|
||||
<script type="application/javascript" src="mediaStreamPlayback.js"></script>
|
||||
<script type="application/javascript" src="nonTrickleIce.js"></script>
|
||||
<script type="application/javascript" src="pc.js"></script>
|
||||
<script type="application/javascript" src="templates.js"></script>
|
||||
<script type="application/javascript" src="turnConfig.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<pre id="test">
|
||||
<script type="application/javascript">
|
||||
createHTML({
|
||||
bug: "1060102",
|
||||
title: "Basic audio only SDP offer and answer without trickle ICE"
|
||||
});
|
||||
|
||||
var test;
|
||||
runNetworkTest(function (options) {
|
||||
test = new PeerConnectionTest(options);
|
||||
makeOffererNonTrickle(test.chain);
|
||||
makeAnswererNonTrickle(test.chain);
|
||||
test.setMediaConstraints([{audio: true}], [{audio: true}]);
|
||||
test.run();
|
||||
});
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
|
@ -91,12 +91,25 @@ Function Properties of the `Debugger.Memory.prototype` Object
|
|||
|
||||
<code id='drain-alloc-log'>drainAllocationsLog()</code>
|
||||
: When `trackingAllocationSites` is `true`, this method returns an array of
|
||||
allocation sites (as [captured stacks][saved-frame]) for recent `Object`
|
||||
allocations within the set of debuggees. Entries for objects allocated with
|
||||
no JavaScript frames on the stack are `null`. *Recent* is defined as the
|
||||
`maxAllocationsLogLength` most recent `Object` allocations since the last
|
||||
call to `drainAllocationsLog`. Therefore, calling this method effectively
|
||||
clears the log.
|
||||
recent `Object` allocations within the set of debuggees. *Recent* is
|
||||
defined as the `maxAllocationsLogLength` most recent `Object` allocations
|
||||
since the last call to `drainAllocationsLog`. Therefore, calling this
|
||||
method effectively clears the log.
|
||||
|
||||
Objects in the array are of the form:
|
||||
|
||||
<pre class='language-js'><code>
|
||||
{
|
||||
"timestamp": <i>timestamp</i>,
|
||||
"frame": <i>allocationSite</i>
|
||||
}
|
||||
</code></pre>
|
||||
|
||||
Here <i>timestamp</i> is the timestamp of the event in units of
|
||||
microseconds since the epoch and <i>allocationSite</i> is an
|
||||
allocation site (as a [captured stack][saved-frame]).
|
||||
<i>allocationSite</i> is `null` for objects allocated with no
|
||||
JavaScript frames on the stack.
|
||||
|
||||
When `trackingAllocationSites` is `false`, `drainAllocationsLog()` throws an
|
||||
`Error`.
|
||||
|
|
|
@ -83,7 +83,7 @@ them.
|
|||
// are new, and Firefox doesn't yet understand that they
|
||||
// are safe for chrome code to use, so we must tell it
|
||||
// so explicitly.
|
||||
site = Components.utils.waiveXrays(site);
|
||||
site = Components.utils.waiveXrays(site.frame);
|
||||
|
||||
if (!counts.has(site))
|
||||
counts.set(site, 0);
|
||||
|
|
|
@ -25,7 +25,7 @@ let idx = -1;
|
|||
for (let object of root.tests) {
|
||||
let wrappedObject = wrappedRoot.makeDebuggeeValue(object);
|
||||
let allocSite = wrappedObject.allocationSite;
|
||||
let newIdx = allocs.indexOf(allocSite);
|
||||
let newIdx = allocs.map(x => x.frame).indexOf(allocSite);
|
||||
assertEq(newIdx > idx, true);
|
||||
idx = newIdx;
|
||||
}
|
||||
|
|
|
@ -19,6 +19,6 @@ const allocs = dbg.memory.drainAllocationsLog();
|
|||
// Should have stayed at the maximum length.
|
||||
assertEq(allocs.length, 3);
|
||||
// Should have kept the most recent allocation.
|
||||
assertEq(allocs[2].line, 4);
|
||||
assertEq(allocs[2].frame.line, 4);
|
||||
// Should have thrown away the oldest allocation.
|
||||
assertEq(allocs.map(x => x.line).indexOf(1), -1);
|
||||
assertEq(allocs.map(x => x.frame.line).indexOf(1), -1);
|
||||
|
|
|
@ -21,10 +21,10 @@ let allocs1 = dbg.memory.drainAllocationsLog();
|
|||
root.doSecondAlloc();
|
||||
let allocs2 = dbg.memory.drainAllocationsLog();
|
||||
|
||||
let allocs1Lines = allocs1.map(x => x.line);
|
||||
let allocs1Lines = allocs1.map(x => x.frame.line);
|
||||
assertEq(allocs1Lines.indexOf(root.firstAllocLine) != -1, true);
|
||||
assertEq(allocs1Lines.indexOf(root.secondAllocLine) == -1, true);
|
||||
|
||||
let allocs2Lines = allocs2.map(x => x.line);
|
||||
let allocs2Lines = allocs2.map(x => x.frame.line);
|
||||
assertEq(allocs2Lines.indexOf(root.secondAllocLine) != -1, true);
|
||||
assertEq(allocs2Lines.indexOf(root.firstAllocLine) == -1, true);
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
// Test that drainAllocationsLog returns some timestamps.
|
||||
|
||||
load(libdir + 'asserts.js');
|
||||
|
||||
var allocTimes = [];
|
||||
|
||||
allocTimes.push(1000 * dateNow());
|
||||
|
||||
const root = newGlobal();
|
||||
const dbg = new Debugger(root);
|
||||
|
||||
dbg.memory.trackingAllocationSites = true;
|
||||
root.eval("this.alloc1 = {}");
|
||||
allocTimes.push(1000 * dateNow());
|
||||
root.eval("this.alloc2 = {}");
|
||||
allocTimes.push(1000 * dateNow());
|
||||
root.eval("this.alloc3 = {}");
|
||||
allocTimes.push(1000 * dateNow());
|
||||
root.eval("this.alloc4 = {}");
|
||||
allocTimes.push(1000 * dateNow());
|
||||
|
||||
allocs = dbg.memory.drainAllocationsLog();
|
||||
assertEq(allocs.length >= 4, true);
|
||||
assertEq(allocs[0].timestamp >= allocTimes[0], true);
|
||||
var seenAlloc = 0;
|
||||
var lastIndexSeenAllocIncremented = 0;
|
||||
for (i = 1; i < allocs.length; ++i) {
|
||||
assertEq(allocs[i].timestamp >= allocs[i - 1].timestamp, true);
|
||||
// It isn't possible to exactly correlate the entries in the
|
||||
// allocs array with the entries in allocTimes, because we can't
|
||||
// control exactly how many allocations are done during the course
|
||||
// of a given eval. However, we can assume that there is some
|
||||
// allocation recorded after each entry in allocTimes. So, we
|
||||
// track the allocTimes entry we've passed, and then after the
|
||||
// loop assert that we've seen them all. We also assert that a
|
||||
// non-zero number of allocations has happened since the last seen
|
||||
// increment.
|
||||
while (seenAlloc < allocTimes.length
|
||||
&& allocs[i].timestamp >= allocTimes[seenAlloc]) {
|
||||
assertEq(i - lastIndexSeenAllocIncremented > 0, true);
|
||||
lastIndexSeenAllocIncremented = i;
|
||||
++seenAlloc;
|
||||
}
|
||||
}
|
||||
// There should be one entry left in allocTimes, because we recorded a
|
||||
// time after the last possible allocation in the array.
|
||||
assertEq(seenAlloc, allocTimes.length -1);
|
|
@ -0,0 +1,5 @@
|
|||
function foo() {
|
||||
for(__key in null)
|
||||
var key=startTest(VERSION) ? this : this;
|
||||
if (key !== undefined) {}
|
||||
} foo();
|
|
@ -866,10 +866,16 @@ FilterTypeSetPolicy::adjustInputs(TempAllocator &alloc, MInstruction *ins)
|
|||
return true;
|
||||
}
|
||||
|
||||
// The outputType should always be a subset of the inputType.
|
||||
// So if types don't equal, the input type is definitely a MIRType_Value.
|
||||
if (inputType != MIRType_Value)
|
||||
MOZ_CRASH("Types should be in accordance.");
|
||||
// The outputType should be a subset of the inputType else we are in code
|
||||
// that has never executed yet. Bail to see the new type (if that hasn't
|
||||
// happened yet).
|
||||
if (inputType != MIRType_Value) {
|
||||
MBail *bail = MBail::New(alloc);
|
||||
ins->block()->insertBefore(ins, bail);
|
||||
bail->setDependency(ins->dependency());
|
||||
ins->setDependency(bail);
|
||||
ins->replaceOperand(0, boxAt(alloc, ins, ins->getOperand(0)));
|
||||
}
|
||||
|
||||
// We can't unbox a value to null/undefined/lazyargs. So keep output
|
||||
// also a value.
|
||||
|
|
|
@ -75,6 +75,7 @@
|
|||
macro(float32x4, float32x4, "float32x4") \
|
||||
macro(float64, float64, "float64") \
|
||||
macro(format, format, "format") \
|
||||
macro(frame, frame, "frame") \
|
||||
macro(from, from, "from") \
|
||||
macro(get, get, "get") \
|
||||
macro(getInternals, getInternals, "getInternals") \
|
||||
|
@ -175,6 +176,7 @@
|
|||
macro(style, style, "style") \
|
||||
macro(test, test, "test") \
|
||||
macro(throw, throw_, "throw") \
|
||||
macro(timestamp, timestamp, "timestamp") \
|
||||
macro(timeZone, timeZone, "timeZone") \
|
||||
macro(toGMTString, toGMTString, "toGMTString") \
|
||||
macro(toISOString, toISOString, "toISOString") \
|
||||
|
|
|
@ -1514,7 +1514,7 @@ Debugger::slowPathOnNewGlobalObject(JSContext *cx, Handle<GlobalObject *> global
|
|||
}
|
||||
|
||||
/* static */ bool
|
||||
Debugger::slowPathOnLogAllocationSite(JSContext *cx, HandleSavedFrame frame,
|
||||
Debugger::slowPathOnLogAllocationSite(JSContext *cx, HandleSavedFrame frame, int64_t when,
|
||||
GlobalObject::DebuggerVector &dbgs)
|
||||
{
|
||||
MOZ_ASSERT(!dbgs.empty());
|
||||
|
@ -1527,7 +1527,7 @@ Debugger::slowPathOnLogAllocationSite(JSContext *cx, HandleSavedFrame frame,
|
|||
|
||||
if ((*dbgp)->trackingAllocationSites &&
|
||||
(*dbgp)->enabled &&
|
||||
!(*dbgp)->appendAllocationSite(cx, frame))
|
||||
!(*dbgp)->appendAllocationSite(cx, frame, when))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
@ -1537,14 +1537,14 @@ Debugger::slowPathOnLogAllocationSite(JSContext *cx, HandleSavedFrame frame,
|
|||
}
|
||||
|
||||
bool
|
||||
Debugger::appendAllocationSite(JSContext *cx, HandleSavedFrame frame)
|
||||
Debugger::appendAllocationSite(JSContext *cx, HandleSavedFrame frame, int64_t when)
|
||||
{
|
||||
AutoCompartment ac(cx, object);
|
||||
RootedObject wrapped(cx, frame);
|
||||
if (!cx->compartment()->wrap(cx, &wrapped))
|
||||
return false;
|
||||
|
||||
AllocationSite *allocSite = cx->new_<AllocationSite>(wrapped);
|
||||
AllocationSite *allocSite = cx->new_<AllocationSite>(wrapped, when);
|
||||
if (!allocSite)
|
||||
return false;
|
||||
|
||||
|
|
|
@ -202,10 +202,11 @@ class Debugger : private mozilla::LinkedListElement<Debugger>
|
|||
|
||||
struct AllocationSite : public mozilla::LinkedListElement<AllocationSite>
|
||||
{
|
||||
explicit AllocationSite(HandleObject frame) : frame(frame) {
|
||||
AllocationSite(HandleObject frame, int64_t when) : frame(frame), when(when) {
|
||||
MOZ_ASSERT_IF(frame, UncheckedUnwrap(frame)->is<SavedFrame>());
|
||||
};
|
||||
RelocatablePtrObject frame;
|
||||
int64_t when;
|
||||
};
|
||||
typedef mozilla::LinkedList<AllocationSite> AllocationSiteList;
|
||||
|
||||
|
@ -215,7 +216,7 @@ class Debugger : private mozilla::LinkedListElement<Debugger>
|
|||
size_t allocationsLogLength;
|
||||
size_t maxAllocationsLogLength;
|
||||
static const size_t DEFAULT_MAX_ALLOCATIONS_LOG_LENGTH = 5000;
|
||||
bool appendAllocationSite(JSContext *cx, HandleSavedFrame frame);
|
||||
bool appendAllocationSite(JSContext *cx, HandleSavedFrame frame, int64_t when);
|
||||
void emptyAllocationsLog();
|
||||
|
||||
/*
|
||||
|
@ -376,7 +377,7 @@ class Debugger : private mozilla::LinkedListElement<Debugger>
|
|||
GlobalObject *compileAndGoGlobal);
|
||||
static void slowPathOnNewGlobalObject(JSContext *cx, Handle<GlobalObject *> global);
|
||||
static bool slowPathOnLogAllocationSite(JSContext *cx, HandleSavedFrame frame,
|
||||
GlobalObject::DebuggerVector &dbgs);
|
||||
int64_t when, GlobalObject::DebuggerVector &dbgs);
|
||||
static JSTrapStatus dispatchHook(JSContext *cx, MutableHandleValue vp, Hook which);
|
||||
|
||||
JSTrapStatus fireDebuggerStatement(JSContext *cx, MutableHandleValue vp);
|
||||
|
@ -509,7 +510,7 @@ class Debugger : private mozilla::LinkedListElement<Debugger>
|
|||
static inline JSTrapStatus onExceptionUnwind(JSContext *cx, AbstractFramePtr frame);
|
||||
static inline void onNewScript(JSContext *cx, HandleScript script, GlobalObject *compileAndGoGlobal);
|
||||
static inline void onNewGlobalObject(JSContext *cx, Handle<GlobalObject *> global);
|
||||
static inline bool onLogAllocationSite(JSContext *cx, HandleSavedFrame frame);
|
||||
static inline bool onLogAllocationSite(JSContext *cx, HandleSavedFrame frame, int64_t when);
|
||||
static JSTrapStatus onTrap(JSContext *cx, MutableHandleValue vp);
|
||||
static JSTrapStatus onSingleStep(JSContext *cx, MutableHandleValue vp);
|
||||
static bool handleBaselineOsr(JSContext *cx, InterpreterFrame *from, jit::BaselineFrame *to);
|
||||
|
@ -832,12 +833,12 @@ Debugger::onNewGlobalObject(JSContext *cx, Handle<GlobalObject *> global)
|
|||
}
|
||||
|
||||
bool
|
||||
Debugger::onLogAllocationSite(JSContext *cx, HandleSavedFrame frame)
|
||||
Debugger::onLogAllocationSite(JSContext *cx, HandleSavedFrame frame, int64_t when)
|
||||
{
|
||||
GlobalObject::DebuggerVector *dbgs = cx->global()->getDebuggers();
|
||||
if (!dbgs || dbgs->empty())
|
||||
return true;
|
||||
return Debugger::slowPathOnLogAllocationSite(cx, frame, *dbgs);
|
||||
return Debugger::slowPathOnLogAllocationSite(cx, frame, when, *dbgs);
|
||||
}
|
||||
|
||||
extern bool
|
||||
|
|
|
@ -199,9 +199,21 @@ DebuggerMemory::drainAllocationsLog(JSContext *cx, unsigned argc, Value *vp)
|
|||
result->ensureDenseInitializedLength(cx, 0, length);
|
||||
|
||||
for (size_t i = 0; i < length; i++) {
|
||||
Debugger::AllocationSite *allocSite = dbg->allocationsLog.popFirst();
|
||||
result->setDenseElement(i, ObjectOrNullValue(allocSite->frame));
|
||||
js_delete(allocSite);
|
||||
RootedObject obj(cx, NewBuiltinClassInstance(cx, &JSObject::class_));
|
||||
if (!obj)
|
||||
return false;
|
||||
|
||||
mozilla::UniquePtr<Debugger::AllocationSite, JS::DeletePolicy<Debugger::AllocationSite> >
|
||||
allocSite(dbg->allocationsLog.popFirst());
|
||||
RootedValue frame(cx, ObjectOrNullValue(allocSite->frame));
|
||||
if (!JSObject::defineProperty(cx, obj, cx->names().frame, frame))
|
||||
return false;
|
||||
|
||||
RootedValue timestampValue(cx, NumberValue(allocSite->when));
|
||||
if (!JSObject::defineProperty(cx, obj, cx->names().timestamp, timestampValue))
|
||||
return false;
|
||||
|
||||
result->setDenseElement(i, ObjectValue(*obj));
|
||||
}
|
||||
|
||||
dbg->allocationsLogLength = 0;
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include "jshashutil.h"
|
||||
#include "jsmath.h"
|
||||
#include "jsnum.h"
|
||||
#include "prmjtime.h"
|
||||
|
||||
#include "gc/Marking.h"
|
||||
#include "js/Vector.h"
|
||||
|
@ -808,7 +809,7 @@ SavedStacksMetadataCallback(JSContext *cx, JSObject **pmetadata)
|
|||
return false;
|
||||
*pmetadata = frame;
|
||||
|
||||
return Debugger::onLogAllocationSite(cx, frame);
|
||||
return Debugger::onLogAllocationSite(cx, frame, PRMJ_Now());
|
||||
}
|
||||
|
||||
#ifdef JS_CRASH_DIAGNOSTICS
|
||||
|
|
|
@ -1402,18 +1402,16 @@ Init(const malloc_table_t* aMallocTable)
|
|||
// - Otherwise, the contents dictate DMD's behaviour.
|
||||
|
||||
char* e = getenv("DMD");
|
||||
StatusMsg("$DMD = '%s'\n", e);
|
||||
|
||||
if (!e || strcmp(e, "") == 0 || strcmp(e, "0") == 0) {
|
||||
StatusMsg("DMD is not enabled\n");
|
||||
return;
|
||||
}
|
||||
|
||||
StatusMsg("$DMD = '%s'\n", e);
|
||||
|
||||
// Parse $DMD env var.
|
||||
gOptions = InfallibleAllocPolicy::new_<Options>(e);
|
||||
|
||||
StatusMsg("DMD is enabled\n");
|
||||
|
||||
#ifdef XP_MACOSX
|
||||
// On Mac OS X we need to call StackWalkInitCriticalAddress() very early
|
||||
// (prior to the creation of any mutexes, apparently) otherwise we can get
|
||||
|
@ -1445,6 +1443,10 @@ Init(const malloc_table_t* aMallocTable)
|
|||
// Do all necessary allocations before setting gIsDMDRunning so those
|
||||
// allocations don't show up in our results. Once gIsDMDRunning is set we
|
||||
// are intercepting malloc et al. in earnest.
|
||||
//
|
||||
// These files are written to $CWD. It would probably be better to write
|
||||
// them to "TmpD" using the directory service, but that would require
|
||||
// linking DMD with XPCOM.
|
||||
auto f1 = MakeUnique<FpWriteFunc>(OpenOutputFile("full1.json"));
|
||||
auto f2 = MakeUnique<FpWriteFunc>(OpenOutputFile("full2.json"));
|
||||
auto f3 = MakeUnique<FpWriteFunc>(OpenOutputFile("full3.json"));
|
||||
|
@ -1453,11 +1455,15 @@ Init(const malloc_table_t* aMallocTable)
|
|||
|
||||
StatusMsg("running test mode...\n");
|
||||
RunTestMode(Move(f1), Move(f2), Move(f3), Move(f4));
|
||||
StatusMsg("finished test mode\n");
|
||||
exit(0);
|
||||
}
|
||||
StatusMsg("finished test mode; DMD is now disabled again\n");
|
||||
|
||||
gIsDMDRunning = true;
|
||||
// Continue running so that the xpcshell test can complete, but DMD no
|
||||
// longer needs to be running.
|
||||
gIsDMDRunning = false;
|
||||
|
||||
} else {
|
||||
gIsDMDRunning = true;
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
|
@ -1835,36 +1841,52 @@ AnalyzeReports(JSONWriter& aWriter)
|
|||
|
||||
// This function checks that heap blocks that have the same stack trace but
|
||||
// different (or no) reporters get aggregated separately.
|
||||
void foo()
|
||||
void Foo(int aSeven)
|
||||
{
|
||||
char* a[6];
|
||||
for (int i = 0; i < 6; i++) {
|
||||
a[i] = (char*) malloc(128 - 16*i);
|
||||
}
|
||||
char* a[6];
|
||||
for (int i = 0; i < aSeven - 1; i++) {
|
||||
a[i] = (char*) replace_malloc(128 - 16*i);
|
||||
}
|
||||
|
||||
for (int i = 0; i <= 1; i++)
|
||||
Report(a[i]); // reported
|
||||
Report(a[2]); // reported
|
||||
Report(a[3]); // reported
|
||||
// a[4], a[5] unreported
|
||||
for (int i = 0; i < aSeven - 5; i++) {
|
||||
Report(a[i]); // reported
|
||||
}
|
||||
Report(a[2]); // reported
|
||||
Report(a[3]); // reported
|
||||
// a[4], a[5] unreported
|
||||
}
|
||||
|
||||
// This stops otherwise-unused variables from being optimized away.
|
||||
static void
|
||||
UseItOrLoseIt(void* a)
|
||||
UseItOrLoseIt(void* aPtr, int aSeven)
|
||||
{
|
||||
char buf[64];
|
||||
sprintf(buf, "%p\n", a);
|
||||
fwrite(buf, 1, strlen(buf) + 1, stderr);
|
||||
int n = sprintf(buf, "%p\n", aPtr);
|
||||
if (n == 20 + aSeven) {
|
||||
fprintf(stderr, "well, that is surprising");
|
||||
}
|
||||
}
|
||||
|
||||
// The output from this should be tested with check_test_output.py. It's been
|
||||
// tested on Linux64, and probably will give different results on other
|
||||
// platforms.
|
||||
// The output from this function feeds into DMD's xpcshell test.
|
||||
static void
|
||||
RunTestMode(UniquePtr<FpWriteFunc> aF1, UniquePtr<FpWriteFunc> aF2,
|
||||
UniquePtr<FpWriteFunc> aF3, UniquePtr<FpWriteFunc> aF4)
|
||||
{
|
||||
// This test relies on the compiler not doing various optimizations, such as
|
||||
// eliding unused replace_malloc() calls or unrolling loops with fixed
|
||||
// iteration counts. So we want a constant value that the compiler can't
|
||||
// determine statically, and we use that in various ways to prevent the above
|
||||
// optimizations from happening.
|
||||
//
|
||||
// This code always sets |seven| to the value 7. It works because we know
|
||||
// that "--mode=test" must be within the DMD environment variable if we reach
|
||||
// here, but the compiler almost certainly does not.
|
||||
//
|
||||
char* env = getenv("DMD");
|
||||
char* p1 = strstr(env, "--mode=t");
|
||||
char* p2 = strstr(p1, "test");
|
||||
int seven = p2 - p1;
|
||||
|
||||
// The first part of this test requires sampling to be disabled.
|
||||
gOptions->SetSampleBelowSize(1);
|
||||
|
||||
|
@ -1879,37 +1901,37 @@ RunTestMode(UniquePtr<FpWriteFunc> aF1, UniquePtr<FpWriteFunc> aF2,
|
|||
// AnalyzeReports 2: 1 freed, 9 out of 10 unreported.
|
||||
// AnalyzeReports 3: still present and unreported.
|
||||
int i;
|
||||
char* a;
|
||||
for (i = 0; i < 10; i++) {
|
||||
a = (char*) malloc(100);
|
||||
UseItOrLoseIt(a);
|
||||
char* a = nullptr;
|
||||
for (i = 0; i < seven + 3; i++) {
|
||||
a = (char*) replace_malloc(100);
|
||||
UseItOrLoseIt(a, seven);
|
||||
}
|
||||
free(a);
|
||||
replace_free(a);
|
||||
|
||||
// Min-sized block.
|
||||
// Note: 8 bytes is the smallest requested size that gives consistent
|
||||
// behaviour across all platforms with jemalloc.
|
||||
// AnalyzeReports 2: reported.
|
||||
// AnalyzeReports 3: thrice-reported.
|
||||
char* a2 = (char*) malloc(0);
|
||||
char* a2 = (char*) replace_malloc(8);
|
||||
Report(a2);
|
||||
|
||||
// Operator new[].
|
||||
// AnalyzeReports 2: reported.
|
||||
// AnalyzeReports 3: reportedness carries over, due to ReportOnAlloc.
|
||||
char* b = new char[10];
|
||||
char* b = (char*) replace_malloc(10);
|
||||
ReportOnAlloc(b);
|
||||
|
||||
// ReportOnAlloc, then freed.
|
||||
// AnalyzeReports 2: freed, irrelevant.
|
||||
// AnalyzeReports 3: freed, irrelevant.
|
||||
char* b2 = new char;
|
||||
char* b2 = (char*) replace_malloc(1);
|
||||
ReportOnAlloc(b2);
|
||||
free(b2);
|
||||
replace_free(b2);
|
||||
|
||||
// AnalyzeReports 2: reported 4 times.
|
||||
// AnalyzeReports 3: freed, irrelevant.
|
||||
char* c = (char*) calloc(10, 3);
|
||||
char* c = (char*) replace_calloc(10, 3);
|
||||
Report(c);
|
||||
for (int i = 0; i < 3; i++) {
|
||||
for (int i = 0; i < seven - 4; i++) {
|
||||
Report(c);
|
||||
}
|
||||
|
||||
|
@ -1920,30 +1942,30 @@ RunTestMode(UniquePtr<FpWriteFunc> aF1, UniquePtr<FpWriteFunc> aF2,
|
|||
// jemalloc rounds this up to 8192.
|
||||
// AnalyzeReports 2: reported.
|
||||
// AnalyzeReports 3: freed.
|
||||
char* e = (char*) malloc(4096);
|
||||
e = (char*) realloc(e, 4097);
|
||||
char* e = (char*) replace_malloc(4096);
|
||||
e = (char*) replace_realloc(e, 4097);
|
||||
Report(e);
|
||||
|
||||
// First realloc is like malloc; second realloc is shrinking.
|
||||
// AnalyzeReports 2: reported.
|
||||
// AnalyzeReports 3: re-reported.
|
||||
char* e2 = (char*) realloc(nullptr, 1024);
|
||||
e2 = (char*) realloc(e2, 512);
|
||||
char* e2 = (char*) replace_realloc(nullptr, 1024);
|
||||
e2 = (char*) replace_realloc(e2, 512);
|
||||
Report(e2);
|
||||
|
||||
// First realloc is like malloc; second realloc creates a min-sized block.
|
||||
// XXX: on Windows, second realloc frees the block.
|
||||
// AnalyzeReports 2: reported.
|
||||
// AnalyzeReports 3: freed, irrelevant.
|
||||
char* e3 = (char*) realloc(nullptr, 1023);
|
||||
//e3 = (char*) realloc(e3, 0);
|
||||
char* e3 = (char*) replace_realloc(nullptr, 1023);
|
||||
//e3 = (char*) replace_realloc(e3, 0);
|
||||
MOZ_ASSERT(e3);
|
||||
Report(e3);
|
||||
|
||||
// AnalyzeReports 2: freed, irrelevant.
|
||||
// AnalyzeReports 3: freed, irrelevant.
|
||||
char* f = (char*) malloc(64);
|
||||
free(f);
|
||||
char* f = (char*) replace_malloc(64);
|
||||
replace_free(f);
|
||||
|
||||
// AnalyzeReports 2: ignored.
|
||||
// AnalyzeReports 3: irrelevant.
|
||||
|
@ -1951,24 +1973,24 @@ RunTestMode(UniquePtr<FpWriteFunc> aF1, UniquePtr<FpWriteFunc> aF2,
|
|||
|
||||
// AnalyzeReports 2: mixture of reported and unreported.
|
||||
// AnalyzeReports 3: all unreported.
|
||||
foo();
|
||||
foo();
|
||||
Foo(seven);
|
||||
Foo(seven);
|
||||
|
||||
// AnalyzeReports 2: twice-reported.
|
||||
// AnalyzeReports 3: twice-reported.
|
||||
char* g1 = (char*) malloc(77);
|
||||
char* g1 = (char*) replace_malloc(77);
|
||||
ReportOnAlloc(g1);
|
||||
ReportOnAlloc(g1);
|
||||
|
||||
// AnalyzeReports 2: twice-reported.
|
||||
// AnalyzeReports 3: once-reported.
|
||||
char* g2 = (char*) malloc(78);
|
||||
char* g2 = (char*) replace_malloc(78);
|
||||
Report(g2);
|
||||
ReportOnAlloc(g2);
|
||||
|
||||
// AnalyzeReports 2: twice-reported.
|
||||
// AnalyzeReports 3: once-reported.
|
||||
char* g3 = (char*) malloc(79);
|
||||
char* g3 = (char*) replace_malloc(79);
|
||||
ReportOnAlloc(g3);
|
||||
Report(g3);
|
||||
|
||||
|
@ -1977,14 +1999,14 @@ RunTestMode(UniquePtr<FpWriteFunc> aF1, UniquePtr<FpWriteFunc> aF2,
|
|||
// AnalyzeReports 3: all freed, irrelevant.
|
||||
// XXX: no memalign on Mac
|
||||
//void* x = memalign(64, 65); // rounds up to 128
|
||||
//UseItOrLoseIt(x);
|
||||
//UseItOrLoseIt(x, seven);
|
||||
// XXX: posix_memalign doesn't work on B2G
|
||||
//void* y;
|
||||
//posix_memalign(&y, 128, 129); // rounds up to 256
|
||||
//UseItOrLoseIt(y);
|
||||
//UseItOrLoseIt(y, seven);
|
||||
// XXX: valloc doesn't work on Windows.
|
||||
//void* z = valloc(1); // rounds up to 4096
|
||||
//UseItOrLoseIt(z);
|
||||
//UseItOrLoseIt(z, seven);
|
||||
//aligned_alloc(64, 256); // XXX: C11 only
|
||||
|
||||
// AnalyzeReports 2.
|
||||
|
@ -1995,13 +2017,13 @@ RunTestMode(UniquePtr<FpWriteFunc> aF1, UniquePtr<FpWriteFunc> aF2,
|
|||
|
||||
Report(a2);
|
||||
Report(a2);
|
||||
free(c);
|
||||
free(e);
|
||||
replace_free(c);
|
||||
replace_free(e);
|
||||
Report(e2);
|
||||
free(e3);
|
||||
//free(x);
|
||||
//free(y);
|
||||
//free(z);
|
||||
replace_free(e3);
|
||||
//replace_free(x);
|
||||
//replace_free(y);
|
||||
//replace_free(z);
|
||||
|
||||
// AnalyzeReports 3.
|
||||
JSONWriter writer3(Move(aF3));
|
||||
|
@ -2018,50 +2040,50 @@ RunTestMode(UniquePtr<FpWriteFunc> aF1, UniquePtr<FpWriteFunc> aF2,
|
|||
|
||||
// This equals the sample size, and so is reported exactly. It should be
|
||||
// listed before records of the same size that are sampled.
|
||||
s = (char*) malloc(128);
|
||||
UseItOrLoseIt(s);
|
||||
s = (char*) replace_malloc(128);
|
||||
UseItOrLoseIt(s, seven);
|
||||
|
||||
// This exceeds the sample size, and so is reported exactly.
|
||||
s = (char*) malloc(144);
|
||||
UseItOrLoseIt(s);
|
||||
s = (char*) replace_malloc(144);
|
||||
UseItOrLoseIt(s, seven);
|
||||
|
||||
// These together constitute exactly one sample.
|
||||
for (int i = 0; i < 16; i++) {
|
||||
s = (char*) malloc(8);
|
||||
UseItOrLoseIt(s);
|
||||
for (int i = 0; i < seven + 9; i++) {
|
||||
s = (char*) replace_malloc(8);
|
||||
UseItOrLoseIt(s, seven);
|
||||
}
|
||||
MOZ_ASSERT(gSmallBlockActualSizeCounter == 0);
|
||||
|
||||
// These fall 8 bytes short of a full sample.
|
||||
for (int i = 0; i < 15; i++) {
|
||||
s = (char*) malloc(8);
|
||||
UseItOrLoseIt(s);
|
||||
for (int i = 0; i < seven + 8; i++) {
|
||||
s = (char*) replace_malloc(8);
|
||||
UseItOrLoseIt(s, seven);
|
||||
}
|
||||
MOZ_ASSERT(gSmallBlockActualSizeCounter == 120);
|
||||
|
||||
// This exceeds the sample size, and so is recorded exactly.
|
||||
s = (char*) malloc(256);
|
||||
UseItOrLoseIt(s);
|
||||
s = (char*) replace_malloc(256);
|
||||
UseItOrLoseIt(s, seven);
|
||||
MOZ_ASSERT(gSmallBlockActualSizeCounter == 120);
|
||||
|
||||
// This gets more than to a full sample from the |i < 15| loop above.
|
||||
s = (char*) malloc(96);
|
||||
UseItOrLoseIt(s);
|
||||
s = (char*) replace_malloc(96);
|
||||
UseItOrLoseIt(s, seven);
|
||||
MOZ_ASSERT(gSmallBlockActualSizeCounter == 88);
|
||||
|
||||
// This gets to another full sample.
|
||||
for (int i = 0; i < 5; i++) {
|
||||
s = (char*) malloc(8);
|
||||
UseItOrLoseIt(s);
|
||||
for (int i = 0; i < seven - 2; i++) {
|
||||
s = (char*) replace_malloc(8);
|
||||
UseItOrLoseIt(s, seven);
|
||||
}
|
||||
MOZ_ASSERT(gSmallBlockActualSizeCounter == 0);
|
||||
|
||||
// This allocates 16, 32, ..., 128 bytes, which results in a heap block
|
||||
// record that contains a mix of sample and non-sampled blocks, and so should
|
||||
// be printed with '~' signs.
|
||||
for (int i = 1; i <= 8; i++) {
|
||||
s = (char*) malloc(i * 16);
|
||||
UseItOrLoseIt(s);
|
||||
for (int i = 1; i <= seven + 1; i++) {
|
||||
s = (char*) replace_malloc(i * 16);
|
||||
UseItOrLoseIt(s, seven);
|
||||
}
|
||||
MOZ_ASSERT(gSmallBlockActualSizeCounter == 64);
|
||||
|
||||
|
|
|
@ -1,127 +0,0 @@
|
|||
#! /usr/bin/python
|
||||
#
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
"""This script takes the file produced by DMD's test mode and checks its
|
||||
correctness.
|
||||
|
||||
It produces the following output files: $TMP/full-{fixed,filtered,diff}.dmd.
|
||||
|
||||
It runs the appropriate fix* script to get nice stack traces. It also
|
||||
filters out platform-specific details from the test output file.
|
||||
|
||||
Note: you must run this from the same directory that you invoked DMD's test
|
||||
mode, otherwise the fix* script will not work properly, because some of the
|
||||
paths in the test output are relative.
|
||||
|
||||
"""
|
||||
|
||||
from __future__ import print_function
|
||||
|
||||
import os
|
||||
import platform
|
||||
import re
|
||||
import subprocess
|
||||
import sys
|
||||
import tempfile
|
||||
|
||||
def test(src_dir, kind, options, i):
|
||||
# Filenames
|
||||
tmp_dir = tempfile.gettempdir()
|
||||
in_name = os.path.join(src_dir, "full{:d}.json".format(i))
|
||||
fixed_name = os.path.join(tmp_dir, "full-{:}-fixed{:d}.json".format(kind, i))
|
||||
converted_name = os.path.join(tmp_dir, "full-{:}-converted{:d}.txt".format(kind, i))
|
||||
filtered_name = os.path.join(tmp_dir, "full-{:}-filtered{:d}.txt".format(kind, i))
|
||||
diff_name = os.path.join(tmp_dir, "full-{:}-diff{:d}.txt".format(kind, i))
|
||||
expected_name = os.path.join(src_dir, "memory", "replace", "dmd", "test", "full-{:}-expected{:d}.txt".format(kind, i))
|
||||
|
||||
# Fix stack traces
|
||||
|
||||
sys_name = platform.system()
|
||||
fix = os.path.join(src_dir, "tools", "rb")
|
||||
if sys_name == "Linux":
|
||||
fix = os.path.join(fix, "fix_linux_stack.py")
|
||||
elif sys_name == "Darwin":
|
||||
fix = os.path.join(fix, "fix_macosx_stack.py")
|
||||
else:
|
||||
print("unhandled platform: " + sys_name, file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
subprocess.call(fix, stdin=open(in_name, "r"),
|
||||
stdout=open(fixed_name, "w"))
|
||||
|
||||
# Convert from JSON
|
||||
|
||||
convert = [os.path.join(src_dir, "memory", "replace", "dmd", "dmd.py")] + \
|
||||
options + ['--no-fix-stacks', fixed_name]
|
||||
subprocess.call(convert, stdout=open(converted_name, "w"))
|
||||
|
||||
# Filter output
|
||||
|
||||
# In heap block records we filter out most stack frames. The only thing
|
||||
# we leave behind is a "DMD.cpp" entry if we see one or more frames that
|
||||
# have DMD.cpp in them. There is simply too much variation to do anything
|
||||
# better than that.
|
||||
|
||||
with open(converted_name, "r") as fin, \
|
||||
open(filtered_name, "w") as fout:
|
||||
|
||||
test_frame_re = re.compile(r".*(DMD.cpp)")
|
||||
|
||||
for line in fin:
|
||||
if re.match(r" (Allocated at {|Reported( again)? at {)", line):
|
||||
# It's a heap block record.
|
||||
print(line, end='', file=fout)
|
||||
|
||||
# Filter the stack trace -- print a single line if we see one
|
||||
# or more frames involving DMD.cpp.
|
||||
seen_DMD_frame = False
|
||||
for frame in fin:
|
||||
if re.match(r" ", frame):
|
||||
m = test_frame_re.match(frame)
|
||||
if m:
|
||||
seen_DMD_frame = True
|
||||
else:
|
||||
# We're past the stack trace.
|
||||
if seen_DMD_frame:
|
||||
print(" ... DMD.cpp", file=fout)
|
||||
print(frame, end='', file=fout)
|
||||
break
|
||||
|
||||
else:
|
||||
# A line that needs no special handling. Copy it through.
|
||||
print(line, end='', file=fout)
|
||||
|
||||
# Compare with expected output
|
||||
|
||||
ret = subprocess.call(["diff", "-u", expected_name, filtered_name],
|
||||
stdout=open(diff_name, "w"))
|
||||
|
||||
if ret == 0:
|
||||
print("TEST-PASS | {:} {:d} | ok".format(kind, i))
|
||||
else:
|
||||
print("TEST-UNEXPECTED-FAIL | {:} {:d} | mismatch".format(kind, i))
|
||||
print("Output files:")
|
||||
print("- " + fixed_name);
|
||||
print("- " + converted_name);
|
||||
print("- " + filtered_name);
|
||||
print("- " + diff_name);
|
||||
|
||||
|
||||
def main():
|
||||
if (len(sys.argv) != 2):
|
||||
print("usage:", sys.argv[0], "<topsrcdir>")
|
||||
sys.exit(1)
|
||||
|
||||
src_dir = sys.argv[1]
|
||||
|
||||
ntests = 4
|
||||
for i in range(1, ntests+1):
|
||||
test(src_dir, "reports", [], i)
|
||||
test(src_dir, "heap", ["--ignore-reports"], i)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
|
@ -102,7 +102,8 @@ If no files are specified, read from stdin.
|
|||
Write to stdout unless -o/--output is specified.
|
||||
Stack traces are fixed to show function names, filenames and line numbers
|
||||
unless --no-fix-stacks is specified; stack fixing modifies the original file
|
||||
and may take some time.
|
||||
and may take some time. If specified, the BREAKPAD_SYMBOLS_PATH environment
|
||||
variable is used to find breakpad symbols for stack fixing.
|
||||
'''
|
||||
p = argparse.ArgumentParser(description=description)
|
||||
|
||||
|
@ -129,6 +130,9 @@ and may take some time.
|
|||
p.add_argument('--no-fix-stacks', action='store_true',
|
||||
help='do not fix stacks')
|
||||
|
||||
p.add_argument('--filter-stacks-for-testing', action='store_true',
|
||||
help='filter stack traces; only useful for testing purposes')
|
||||
|
||||
p.add_argument('input_file', type=argparse.FileType('r'))
|
||||
|
||||
return p.parse_args(sys.argv[1:])
|
||||
|
@ -141,10 +145,12 @@ def fixStackTraces(args):
|
|||
# script is installed as a symlink.
|
||||
sys.path.append(os.path.dirname(__file__))
|
||||
|
||||
# XXX: should incorporate fix_stack_using_bpsyms.py here as well, like in
|
||||
# testing/mochitests/runtests.py
|
||||
bpsyms = os.environ.get('BREAKPAD_SYMBOLS_PATH', None)
|
||||
sysname = platform.system()
|
||||
if sysname == 'Linux':
|
||||
if bpsyms and os.path.exists(bpsyms):
|
||||
import fix_stack_using_bpsyms as fixModule
|
||||
fix = lambda line: fixModule.fixSymbols(line, bpsyms)
|
||||
elif sysname == 'Linux':
|
||||
import fix_linux_stack as fixModule
|
||||
fix = lambda line: fixModule.fixSymbols(line)
|
||||
elif sysname == 'Darwin':
|
||||
|
@ -304,10 +310,26 @@ def main():
|
|||
print(*arguments, file=args.output, **kwargs)
|
||||
|
||||
def printStack(traceTable, frameTable, traceKey):
|
||||
frameKeys = traceTable[traceKey]
|
||||
fmt = ' #{:02d}{:}'
|
||||
|
||||
if args.filter_stacks_for_testing:
|
||||
# If any frame has "DMD.cpp" or "replace_malloc.c" in its
|
||||
# description -- as should be the case for every stack trace when
|
||||
# running DMD in test mode -- we replace the entire trace with a
|
||||
# single, predictable frame. There is too much variation in the
|
||||
# stack traces across different machines and platforms to do more
|
||||
# specific matching.
|
||||
for frameKey in frameKeys:
|
||||
frameDesc = frameTable[frameKey]
|
||||
if 'DMD.cpp' in frameDesc or 'replace_malloc.c' in frameDesc:
|
||||
out(fmt.format(1, ': ... DMD.cpp ...'))
|
||||
return
|
||||
|
||||
# The frame number is always '#00' (see DMD.h for why), so we have to
|
||||
# replace that with the correct frame number.
|
||||
for n, frameKey in enumerate(traceTable[traceKey], start=1):
|
||||
out(' #{:02d}{:}'.format(n, frameTable[frameKey][3:]))
|
||||
out(fmt.format(n, frameTable[frameKey][3:]))
|
||||
|
||||
def printRecords(recordKind, records, heapUsableSize):
|
||||
RecordKind = recordKind.capitalize()
|
||||
|
|
|
@ -32,3 +32,8 @@ if CONFIG['OS_ARCH'] == 'WINNT':
|
|||
OS_LIBS += [
|
||||
'dbghelp',
|
||||
]
|
||||
|
||||
XPCSHELL_TESTS_MANIFESTS += [
|
||||
'test/xpcshell.ini',
|
||||
]
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@ Live {
|
|||
8,192 bytes (4,097 requested / 4,095 slop)
|
||||
67.77% of the heap (67.77% cumulative)
|
||||
Allocated at {
|
||||
... DMD.cpp
|
||||
#01: ... DMD.cpp ...
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -21,7 +21,7 @@ Live {
|
|||
1,024 bytes (1,023 requested / 1 slop)
|
||||
8.47% of the heap (76.24% cumulative)
|
||||
Allocated at {
|
||||
... DMD.cpp
|
||||
#01: ... DMD.cpp ...
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -30,7 +30,7 @@ Live {
|
|||
1,008 bytes (900 requested / 108 slop)
|
||||
8.34% of the heap (84.58% cumulative)
|
||||
Allocated at {
|
||||
... DMD.cpp
|
||||
#01: ... DMD.cpp ...
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -39,7 +39,7 @@ Live {
|
|||
528 bytes (528 requested / 0 slop)
|
||||
4.37% of the heap (88.95% cumulative)
|
||||
Allocated at {
|
||||
... DMD.cpp
|
||||
#01: ... DMD.cpp ...
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -48,7 +48,7 @@ Live {
|
|||
528 bytes (528 requested / 0 slop)
|
||||
4.37% of the heap (93.32% cumulative)
|
||||
Allocated at {
|
||||
... DMD.cpp
|
||||
#01: ... DMD.cpp ...
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -57,7 +57,7 @@ Live {
|
|||
512 bytes (512 requested / 0 slop)
|
||||
4.24% of the heap (97.55% cumulative)
|
||||
Allocated at {
|
||||
... DMD.cpp
|
||||
#01: ... DMD.cpp ...
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -66,7 +66,7 @@ Live {
|
|||
80 bytes (79 requested / 1 slop)
|
||||
0.66% of the heap (98.21% cumulative)
|
||||
Allocated at {
|
||||
... DMD.cpp
|
||||
#01: ... DMD.cpp ...
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -75,7 +75,7 @@ Live {
|
|||
80 bytes (78 requested / 2 slop)
|
||||
0.66% of the heap (98.87% cumulative)
|
||||
Allocated at {
|
||||
... DMD.cpp
|
||||
#01: ... DMD.cpp ...
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -84,7 +84,7 @@ Live {
|
|||
80 bytes (77 requested / 3 slop)
|
||||
0.66% of the heap (99.54% cumulative)
|
||||
Allocated at {
|
||||
... DMD.cpp
|
||||
#01: ... DMD.cpp ...
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -93,7 +93,7 @@ Live {
|
|||
32 bytes (30 requested / 2 slop)
|
||||
0.26% of the heap (99.80% cumulative)
|
||||
Allocated at {
|
||||
... DMD.cpp
|
||||
#01: ... DMD.cpp ...
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -102,16 +102,16 @@ Live {
|
|||
16 bytes (10 requested / 6 slop)
|
||||
0.13% of the heap (99.93% cumulative)
|
||||
Allocated at {
|
||||
... DMD.cpp
|
||||
#01: ... DMD.cpp ...
|
||||
}
|
||||
}
|
||||
|
||||
Live {
|
||||
1 block in heap block record 12 of 12
|
||||
8 bytes (0 requested / 8 slop)
|
||||
8 bytes (8 requested / 0 slop)
|
||||
0.07% of the heap (100.00% cumulative)
|
||||
Allocated at {
|
||||
... DMD.cpp
|
||||
#01: ... DMD.cpp ...
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@ Live {
|
|||
1,008 bytes (900 requested / 108 slop)
|
||||
35.49% of the heap (35.49% cumulative)
|
||||
Allocated at {
|
||||
... DMD.cpp
|
||||
#01: ... DMD.cpp ...
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -21,7 +21,7 @@ Live {
|
|||
528 bytes (528 requested / 0 slop)
|
||||
18.59% of the heap (54.08% cumulative)
|
||||
Allocated at {
|
||||
... DMD.cpp
|
||||
#01: ... DMD.cpp ...
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -30,7 +30,7 @@ Live {
|
|||
528 bytes (528 requested / 0 slop)
|
||||
18.59% of the heap (72.68% cumulative)
|
||||
Allocated at {
|
||||
... DMD.cpp
|
||||
#01: ... DMD.cpp ...
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -39,7 +39,7 @@ Live {
|
|||
512 bytes (512 requested / 0 slop)
|
||||
18.03% of the heap (90.70% cumulative)
|
||||
Allocated at {
|
||||
... DMD.cpp
|
||||
#01: ... DMD.cpp ...
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -48,7 +48,7 @@ Live {
|
|||
80 bytes (79 requested / 1 slop)
|
||||
2.82% of the heap (93.52% cumulative)
|
||||
Allocated at {
|
||||
... DMD.cpp
|
||||
#01: ... DMD.cpp ...
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -57,7 +57,7 @@ Live {
|
|||
80 bytes (78 requested / 2 slop)
|
||||
2.82% of the heap (96.34% cumulative)
|
||||
Allocated at {
|
||||
... DMD.cpp
|
||||
#01: ... DMD.cpp ...
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -66,7 +66,7 @@ Live {
|
|||
80 bytes (77 requested / 3 slop)
|
||||
2.82% of the heap (99.15% cumulative)
|
||||
Allocated at {
|
||||
... DMD.cpp
|
||||
#01: ... DMD.cpp ...
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -75,16 +75,16 @@ Live {
|
|||
16 bytes (10 requested / 6 slop)
|
||||
0.56% of the heap (99.72% cumulative)
|
||||
Allocated at {
|
||||
... DMD.cpp
|
||||
#01: ... DMD.cpp ...
|
||||
}
|
||||
}
|
||||
|
||||
Live {
|
||||
1 block in heap block record 9 of 9
|
||||
8 bytes (0 requested / 8 slop)
|
||||
8 bytes (8 requested / 0 slop)
|
||||
0.28% of the heap (100.00% cumulative)
|
||||
Allocated at {
|
||||
... DMD.cpp
|
||||
#01: ... DMD.cpp ...
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@ Live {
|
|||
~512 bytes (~512 requested / ~0 slop)
|
||||
35.96% of the heap (35.96% cumulative)
|
||||
Allocated at {
|
||||
... DMD.cpp
|
||||
#01: ... DMD.cpp ...
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -21,7 +21,7 @@ Live {
|
|||
256 bytes (256 requested / 0 slop)
|
||||
17.98% of the heap (53.93% cumulative)
|
||||
Allocated at {
|
||||
... DMD.cpp
|
||||
#01: ... DMD.cpp ...
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -30,7 +30,7 @@ Live {
|
|||
144 bytes (144 requested / 0 slop)
|
||||
10.11% of the heap (64.04% cumulative)
|
||||
Allocated at {
|
||||
... DMD.cpp
|
||||
#01: ... DMD.cpp ...
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -39,7 +39,7 @@ Live {
|
|||
128 bytes (128 requested / 0 slop)
|
||||
8.99% of the heap (73.03% cumulative)
|
||||
Allocated at {
|
||||
... DMD.cpp
|
||||
#01: ... DMD.cpp ...
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -48,7 +48,7 @@ Live {
|
|||
~128 bytes (~128 requested / ~0 slop)
|
||||
8.99% of the heap (82.02% cumulative)
|
||||
Allocated at {
|
||||
... DMD.cpp
|
||||
#01: ... DMD.cpp ...
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -57,7 +57,7 @@ Live {
|
|||
~128 bytes (~128 requested / ~0 slop)
|
||||
8.99% of the heap (91.01% cumulative)
|
||||
Allocated at {
|
||||
... DMD.cpp
|
||||
#01: ... DMD.cpp ...
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -66,7 +66,7 @@ Live {
|
|||
~128 bytes (~128 requested / ~0 slop)
|
||||
8.99% of the heap (100.00% cumulative)
|
||||
Allocated at {
|
||||
... DMD.cpp
|
||||
#01: ... DMD.cpp ...
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -13,13 +13,13 @@ Twice-reported {
|
|||
0.66% of the heap (0.66% cumulative)
|
||||
29.41% of twice-reported (29.41% cumulative)
|
||||
Allocated at {
|
||||
... DMD.cpp
|
||||
#01: ... DMD.cpp ...
|
||||
}
|
||||
Reported at {
|
||||
... DMD.cpp
|
||||
#01: ... DMD.cpp ...
|
||||
}
|
||||
Reported again at {
|
||||
... DMD.cpp
|
||||
#01: ... DMD.cpp ...
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -29,13 +29,13 @@ Twice-reported {
|
|||
0.66% of the heap (1.32% cumulative)
|
||||
29.41% of twice-reported (58.82% cumulative)
|
||||
Allocated at {
|
||||
... DMD.cpp
|
||||
#01: ... DMD.cpp ...
|
||||
}
|
||||
Reported at {
|
||||
... DMD.cpp
|
||||
#01: ... DMD.cpp ...
|
||||
}
|
||||
Reported again at {
|
||||
... DMD.cpp
|
||||
#01: ... DMD.cpp ...
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -45,13 +45,13 @@ Twice-reported {
|
|||
0.66% of the heap (1.99% cumulative)
|
||||
29.41% of twice-reported (88.24% cumulative)
|
||||
Allocated at {
|
||||
... DMD.cpp
|
||||
#01: ... DMD.cpp ...
|
||||
}
|
||||
Reported at {
|
||||
... DMD.cpp
|
||||
#01: ... DMD.cpp ...
|
||||
}
|
||||
Reported again at {
|
||||
... DMD.cpp
|
||||
#01: ... DMD.cpp ...
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -61,13 +61,13 @@ Twice-reported {
|
|||
0.26% of the heap (2.25% cumulative)
|
||||
11.76% of twice-reported (100.00% cumulative)
|
||||
Allocated at {
|
||||
... DMD.cpp
|
||||
#01: ... DMD.cpp ...
|
||||
}
|
||||
Reported at {
|
||||
... DMD.cpp
|
||||
#01: ... DMD.cpp ...
|
||||
}
|
||||
Reported again at {
|
||||
... DMD.cpp
|
||||
#01: ... DMD.cpp ...
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -79,7 +79,7 @@ Unreported {
|
|||
8.34% of the heap (8.34% cumulative)
|
||||
81.82% of unreported (81.82% cumulative)
|
||||
Allocated at {
|
||||
... DMD.cpp
|
||||
#01: ... DMD.cpp ...
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -89,7 +89,7 @@ Unreported {
|
|||
0.93% of the heap (9.27% cumulative)
|
||||
9.09% of unreported (90.91% cumulative)
|
||||
Allocated at {
|
||||
... DMD.cpp
|
||||
#01: ... DMD.cpp ...
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -99,7 +99,7 @@ Unreported {
|
|||
0.93% of the heap (10.19% cumulative)
|
||||
9.09% of unreported (100.00% cumulative)
|
||||
Allocated at {
|
||||
... DMD.cpp
|
||||
#01: ... DMD.cpp ...
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -111,10 +111,10 @@ Once-reported {
|
|||
67.77% of the heap (67.77% cumulative)
|
||||
77.40% of once-reported (77.40% cumulative)
|
||||
Allocated at {
|
||||
... DMD.cpp
|
||||
#01: ... DMD.cpp ...
|
||||
}
|
||||
Reported at {
|
||||
... DMD.cpp
|
||||
#01: ... DMD.cpp ...
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -124,10 +124,10 @@ Once-reported {
|
|||
8.47% of the heap (76.24% cumulative)
|
||||
9.67% of once-reported (87.07% cumulative)
|
||||
Allocated at {
|
||||
... DMD.cpp
|
||||
#01: ... DMD.cpp ...
|
||||
}
|
||||
Reported at {
|
||||
... DMD.cpp
|
||||
#01: ... DMD.cpp ...
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -137,10 +137,10 @@ Once-reported {
|
|||
4.24% of the heap (80.48% cumulative)
|
||||
4.84% of once-reported (91.91% cumulative)
|
||||
Allocated at {
|
||||
... DMD.cpp
|
||||
#01: ... DMD.cpp ...
|
||||
}
|
||||
Reported at {
|
||||
... DMD.cpp
|
||||
#01: ... DMD.cpp ...
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -150,10 +150,10 @@ Once-reported {
|
|||
1.99% of the heap (82.46% cumulative)
|
||||
2.27% of once-reported (94.18% cumulative)
|
||||
Allocated at {
|
||||
... DMD.cpp
|
||||
#01: ... DMD.cpp ...
|
||||
}
|
||||
Reported at {
|
||||
... DMD.cpp
|
||||
#01: ... DMD.cpp ...
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -163,10 +163,10 @@ Once-reported {
|
|||
1.99% of the heap (84.45% cumulative)
|
||||
2.27% of once-reported (96.45% cumulative)
|
||||
Allocated at {
|
||||
... DMD.cpp
|
||||
#01: ... DMD.cpp ...
|
||||
}
|
||||
Reported at {
|
||||
... DMD.cpp
|
||||
#01: ... DMD.cpp ...
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -176,10 +176,10 @@ Once-reported {
|
|||
0.79% of the heap (85.24% cumulative)
|
||||
0.91% of once-reported (97.35% cumulative)
|
||||
Allocated at {
|
||||
... DMD.cpp
|
||||
#01: ... DMD.cpp ...
|
||||
}
|
||||
Reported at {
|
||||
... DMD.cpp
|
||||
#01: ... DMD.cpp ...
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -189,10 +189,10 @@ Once-reported {
|
|||
0.79% of the heap (86.04% cumulative)
|
||||
0.91% of once-reported (98.26% cumulative)
|
||||
Allocated at {
|
||||
... DMD.cpp
|
||||
#01: ... DMD.cpp ...
|
||||
}
|
||||
Reported at {
|
||||
... DMD.cpp
|
||||
#01: ... DMD.cpp ...
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -202,10 +202,10 @@ Once-reported {
|
|||
0.66% of the heap (86.70% cumulative)
|
||||
0.76% of once-reported (99.02% cumulative)
|
||||
Allocated at {
|
||||
... DMD.cpp
|
||||
#01: ... DMD.cpp ...
|
||||
}
|
||||
Reported at {
|
||||
... DMD.cpp
|
||||
#01: ... DMD.cpp ...
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -215,10 +215,10 @@ Once-reported {
|
|||
0.66% of the heap (87.36% cumulative)
|
||||
0.76% of once-reported (99.77% cumulative)
|
||||
Allocated at {
|
||||
... DMD.cpp
|
||||
#01: ... DMD.cpp ...
|
||||
}
|
||||
Reported at {
|
||||
... DMD.cpp
|
||||
#01: ... DMD.cpp ...
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -228,23 +228,23 @@ Once-reported {
|
|||
0.13% of the heap (87.49% cumulative)
|
||||
0.15% of once-reported (99.92% cumulative)
|
||||
Allocated at {
|
||||
... DMD.cpp
|
||||
#01: ... DMD.cpp ...
|
||||
}
|
||||
Reported at {
|
||||
... DMD.cpp
|
||||
#01: ... DMD.cpp ...
|
||||
}
|
||||
}
|
||||
|
||||
Once-reported {
|
||||
1 block in heap block record 11 of 11
|
||||
8 bytes (0 requested / 8 slop)
|
||||
8 bytes (8 requested / 0 slop)
|
||||
0.07% of the heap (87.56% cumulative)
|
||||
0.08% of once-reported (100.00% cumulative)
|
||||
Allocated at {
|
||||
... DMD.cpp
|
||||
#01: ... DMD.cpp ...
|
||||
}
|
||||
Reported at {
|
||||
... DMD.cpp
|
||||
#01: ... DMD.cpp ...
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -13,29 +13,29 @@ Twice-reported {
|
|||
2.82% of the heap (2.82% cumulative)
|
||||
90.91% of twice-reported (90.91% cumulative)
|
||||
Allocated at {
|
||||
... DMD.cpp
|
||||
#01: ... DMD.cpp ...
|
||||
}
|
||||
Reported at {
|
||||
... DMD.cpp
|
||||
#01: ... DMD.cpp ...
|
||||
}
|
||||
Reported again at {
|
||||
... DMD.cpp
|
||||
#01: ... DMD.cpp ...
|
||||
}
|
||||
}
|
||||
|
||||
Twice-reported {
|
||||
1 block in heap block record 2 of 2
|
||||
8 bytes (0 requested / 8 slop)
|
||||
8 bytes (8 requested / 0 slop)
|
||||
0.28% of the heap (3.10% cumulative)
|
||||
9.09% of twice-reported (100.00% cumulative)
|
||||
Allocated at {
|
||||
... DMD.cpp
|
||||
#01: ... DMD.cpp ...
|
||||
}
|
||||
Reported at {
|
||||
... DMD.cpp
|
||||
#01: ... DMD.cpp ...
|
||||
}
|
||||
Reported again at {
|
||||
... DMD.cpp
|
||||
#01: ... DMD.cpp ...
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -47,7 +47,7 @@ Unreported {
|
|||
35.49% of the heap (35.49% cumulative)
|
||||
48.84% of unreported (48.84% cumulative)
|
||||
Allocated at {
|
||||
... DMD.cpp
|
||||
#01: ... DMD.cpp ...
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -57,7 +57,7 @@ Unreported {
|
|||
18.59% of the heap (54.08% cumulative)
|
||||
25.58% of unreported (74.42% cumulative)
|
||||
Allocated at {
|
||||
... DMD.cpp
|
||||
#01: ... DMD.cpp ...
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -67,7 +67,7 @@ Unreported {
|
|||
18.59% of the heap (72.68% cumulative)
|
||||
25.58% of unreported (100.00% cumulative)
|
||||
Allocated at {
|
||||
... DMD.cpp
|
||||
#01: ... DMD.cpp ...
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -79,10 +79,10 @@ Once-reported {
|
|||
18.03% of the heap (18.03% cumulative)
|
||||
74.42% of once-reported (74.42% cumulative)
|
||||
Allocated at {
|
||||
... DMD.cpp
|
||||
#01: ... DMD.cpp ...
|
||||
}
|
||||
Reported at {
|
||||
... DMD.cpp
|
||||
#01: ... DMD.cpp ...
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -92,10 +92,10 @@ Once-reported {
|
|||
2.82% of the heap (20.85% cumulative)
|
||||
11.63% of once-reported (86.05% cumulative)
|
||||
Allocated at {
|
||||
... DMD.cpp
|
||||
#01: ... DMD.cpp ...
|
||||
}
|
||||
Reported at {
|
||||
... DMD.cpp
|
||||
#01: ... DMD.cpp ...
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -105,10 +105,10 @@ Once-reported {
|
|||
2.82% of the heap (23.66% cumulative)
|
||||
11.63% of once-reported (97.67% cumulative)
|
||||
Allocated at {
|
||||
... DMD.cpp
|
||||
#01: ... DMD.cpp ...
|
||||
}
|
||||
Reported at {
|
||||
... DMD.cpp
|
||||
#01: ... DMD.cpp ...
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -118,10 +118,10 @@ Once-reported {
|
|||
0.56% of the heap (24.23% cumulative)
|
||||
2.33% of once-reported (100.00% cumulative)
|
||||
Allocated at {
|
||||
... DMD.cpp
|
||||
#01: ... DMD.cpp ...
|
||||
}
|
||||
Reported at {
|
||||
... DMD.cpp
|
||||
#01: ... DMD.cpp ...
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@ Unreported {
|
|||
35.96% of the heap (35.96% cumulative)
|
||||
35.96% of unreported (35.96% cumulative)
|
||||
Allocated at {
|
||||
... DMD.cpp
|
||||
#01: ... DMD.cpp ...
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -27,7 +27,7 @@ Unreported {
|
|||
17.98% of the heap (53.93% cumulative)
|
||||
17.98% of unreported (53.93% cumulative)
|
||||
Allocated at {
|
||||
... DMD.cpp
|
||||
#01: ... DMD.cpp ...
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -37,7 +37,7 @@ Unreported {
|
|||
10.11% of the heap (64.04% cumulative)
|
||||
10.11% of unreported (64.04% cumulative)
|
||||
Allocated at {
|
||||
... DMD.cpp
|
||||
#01: ... DMD.cpp ...
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -47,7 +47,7 @@ Unreported {
|
|||
8.99% of the heap (73.03% cumulative)
|
||||
8.99% of unreported (73.03% cumulative)
|
||||
Allocated at {
|
||||
... DMD.cpp
|
||||
#01: ... DMD.cpp ...
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -57,7 +57,7 @@ Unreported {
|
|||
8.99% of the heap (82.02% cumulative)
|
||||
8.99% of unreported (82.02% cumulative)
|
||||
Allocated at {
|
||||
... DMD.cpp
|
||||
#01: ... DMD.cpp ...
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -67,7 +67,7 @@ Unreported {
|
|||
8.99% of the heap (91.01% cumulative)
|
||||
8.99% of unreported (91.01% cumulative)
|
||||
Allocated at {
|
||||
... DMD.cpp
|
||||
#01: ... DMD.cpp ...
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -77,7 +77,7 @@ Unreported {
|
|||
8.99% of the heap (100.00% cumulative)
|
||||
8.99% of unreported (100.00% cumulative)
|
||||
Allocated at {
|
||||
... DMD.cpp
|
||||
#01: ... DMD.cpp ...
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,87 @@
|
|||
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*-*/
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
const {classes: Cc, interfaces: Ci, utils: Cu} = Components
|
||||
|
||||
Cu.import("resource://gre/modules/FileUtils.jsm");
|
||||
|
||||
// The xpcshell test harness sets PYTHON so we can read it here.
|
||||
let gEnv = Cc["@mozilla.org/process/environment;1"]
|
||||
.getService(Ci.nsIEnvironment);
|
||||
let gPythonName = gEnv.get("PYTHON");
|
||||
|
||||
// If we're testing locally, the script is in "CurProcD". Otherwise, it is in
|
||||
// another location that we have to find.
|
||||
let gDmdScriptFile = FileUtils.getFile("CurProcD", ["dmd.py"]);
|
||||
if (!gDmdScriptFile.exists()) {
|
||||
gDmdScriptFile = FileUtils.getFile("CurWorkD", []);
|
||||
while (gDmdScriptFile.path.contains("xpcshell")) {
|
||||
gDmdScriptFile = gDmdScriptFile.parent;
|
||||
}
|
||||
gDmdScriptFile.append("bin");
|
||||
gDmdScriptFile.append("dmd.py");
|
||||
}
|
||||
|
||||
function test(aJsonFile, aKind, aOptions, aN) {
|
||||
// DMD writes the JSON files to CurWorkD, so we do likewise here with
|
||||
// |actualFile| for consistency. It is removed once we've finished.
|
||||
let expectedFile =
|
||||
FileUtils.getFile("CurWorkD",
|
||||
["full-" + aKind + "-expected" + aN + ".txt"]);
|
||||
let actualFile =
|
||||
FileUtils.getFile("CurWorkD",
|
||||
["full-" + aKind + "-actual" + aN + ".txt"]);
|
||||
|
||||
// Run dmd.py on the JSON file, producing |actualFile|.
|
||||
|
||||
let pythonFile = new FileUtils.File(gPythonName);
|
||||
let pythonProcess = Cc["@mozilla.org/process/util;1"]
|
||||
.createInstance(Components.interfaces.nsIProcess);
|
||||
pythonProcess.init(pythonFile);
|
||||
|
||||
let args = [
|
||||
gDmdScriptFile.path,
|
||||
"--filter-stacks-for-testing",
|
||||
"-o", actualFile.path
|
||||
];
|
||||
args = args.concat(aOptions);
|
||||
args.push(aJsonFile.path);
|
||||
|
||||
pythonProcess.run(/* blocking = */true, args, args.length);
|
||||
|
||||
// Compare |expectedFile| with |actualFile|. Difference are printed to
|
||||
// stdout.
|
||||
|
||||
let diffFile = new FileUtils.File("/usr/bin/diff");
|
||||
let diffProcess = Cc["@mozilla.org/process/util;1"]
|
||||
.createInstance(Components.interfaces.nsIProcess);
|
||||
// XXX: this doesn't work on Windows (bug 1076446).
|
||||
diffProcess.init(diffFile);
|
||||
|
||||
args = ["-u", expectedFile.path, actualFile.path];
|
||||
diffProcess.run(/* blocking = */true, args, args.length);
|
||||
let success = diffProcess.exitValue == 0;
|
||||
ok(success, aKind + " " + aN);
|
||||
|
||||
actualFile.remove(true);
|
||||
}
|
||||
|
||||
function run_test() {
|
||||
// These tests do full end-to-end testing of DMD, i.e. both the C++ code that
|
||||
// generates the JSON output, and the script that post-processes that output.
|
||||
// The test relies on DMD's test mode executing beforehand, in order to
|
||||
// produce the relevant JSON files.
|
||||
//
|
||||
// Run these synchronously, because test() updates the full*.json files
|
||||
// in-place (to fix stacks) when it runs dmd.py, and that's not safe to do
|
||||
// asynchronously.
|
||||
for (let i = 1; i <= 4; i++) {
|
||||
let jsonFile = FileUtils.getFile("CurWorkD", ["full" + i + ".json"]);
|
||||
test(jsonFile, "heap", ["--ignore-reports"], i);
|
||||
test(jsonFile, "reports", [], i);
|
||||
jsonFile.remove(true);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
[DEFAULT]
|
||||
support-files =
|
||||
full-heap-expected1.txt
|
||||
full-heap-expected2.txt
|
||||
full-heap-expected3.txt
|
||||
full-heap-expected4.txt
|
||||
full-reports-expected1.txt
|
||||
full-reports-expected2.txt
|
||||
full-reports-expected3.txt
|
||||
full-reports-expected4.txt
|
||||
|
||||
# Bug 1077230 explains why this test is disabled on Mac 10.6.
|
||||
# Bug 1076446 is open for getting this test working on on Windows.
|
||||
[test_dmd.js]
|
||||
dmd = true
|
||||
run-if = os == 'linux' || os == 'mac' && os_version != '10.6'
|
|
@ -582,14 +582,11 @@ nsDNSService::Init()
|
|||
|
||||
mLocalDomains.Clear();
|
||||
if (localDomains) {
|
||||
nsAdoptingString domains;
|
||||
domains.AssignASCII(nsDependentCString(localDomains).get());
|
||||
nsCharSeparatedTokenizer tokenizer(domains, ',',
|
||||
nsCharSeparatedTokenizerTemplate<>::SEPARATOR_OPTIONAL);
|
||||
nsCCharSeparatedTokenizer tokenizer(localDomains, ',',
|
||||
nsCCharSeparatedTokenizer::SEPARATOR_OPTIONAL);
|
||||
|
||||
while (tokenizer.hasMoreTokens()) {
|
||||
const nsSubstring& domain = tokenizer.nextToken();
|
||||
mLocalDomains.PutEntry(nsDependentCString(NS_ConvertUTF16toUTF8(domain).get()));
|
||||
mLocalDomains.PutEntry(tokenizer.nextToken());
|
||||
}
|
||||
}
|
||||
mNotifyResolution = notifyResolution;
|
||||
|
@ -648,9 +645,26 @@ nsDNSService::SetPrefetchEnabled(bool inVal)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
static inline bool PreprocessHostname(bool aLocalDomain,
|
||||
const nsACString &aInput,
|
||||
nsIIDNService *aIDN,
|
||||
nsACString &aACE)
|
||||
{
|
||||
if (aLocalDomain) {
|
||||
aACE.AssignLiteral("localhost");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!aIDN || IsASCII(aInput)) {
|
||||
aACE = aInput;
|
||||
return true;
|
||||
}
|
||||
|
||||
return IsUTF8(aInput) && NS_SUCCEEDED(aIDN->ConvertUTF8toACE(aInput, aACE));
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDNSService::AsyncResolve(const nsACString &hostname,
|
||||
nsDNSService::AsyncResolve(const nsACString &aHostname,
|
||||
uint32_t flags,
|
||||
nsIDNSListener *listener,
|
||||
nsIEventTarget *target_,
|
||||
|
@ -670,12 +684,12 @@ nsDNSService::AsyncResolve(const nsACString &hostname,
|
|||
|
||||
res = mResolver;
|
||||
idn = mIDN;
|
||||
localDomain = mLocalDomains.GetEntry(hostname);
|
||||
localDomain = mLocalDomains.GetEntry(aHostname);
|
||||
}
|
||||
|
||||
if (mNotifyResolution) {
|
||||
NS_DispatchToMainThread(new NotifyDNSResolution(mObserverService,
|
||||
hostname));
|
||||
aHostname));
|
||||
}
|
||||
|
||||
if (!res)
|
||||
|
@ -684,23 +698,9 @@ nsDNSService::AsyncResolve(const nsACString &hostname,
|
|||
if (mOffline)
|
||||
flags |= RESOLVE_OFFLINE;
|
||||
|
||||
const nsACString *hostPtr = &hostname;
|
||||
|
||||
nsAutoCString strLocalhost(NS_LITERAL_CSTRING("localhost"));
|
||||
if (localDomain) {
|
||||
hostPtr = &strLocalhost;
|
||||
}
|
||||
|
||||
nsresult rv;
|
||||
nsAutoCString hostACE;
|
||||
if (idn && !IsASCII(*hostPtr)) {
|
||||
if (IsUTF8(*hostPtr) &&
|
||||
NS_SUCCEEDED(idn->ConvertUTF8toACE(*hostPtr, hostACE))) {
|
||||
hostPtr = &hostACE;
|
||||
} else {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
}
|
||||
nsCString hostname;
|
||||
if (!PreprocessHostname(localDomain, aHostname, idn, hostname))
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
// make sure JS callers get notification on the main thread
|
||||
nsCOMPtr<nsIXPConnectWrappedJS> wrappedListener = do_QueryInterface(listener);
|
||||
|
@ -714,20 +714,20 @@ nsDNSService::AsyncResolve(const nsACString &hostname,
|
|||
listener = new DNSListenerProxy(listener, target);
|
||||
}
|
||||
|
||||
uint16_t af = GetAFForLookup(*hostPtr, flags);
|
||||
uint16_t af = GetAFForLookup(hostname, flags);
|
||||
|
||||
nsDNSAsyncRequest *req =
|
||||
new nsDNSAsyncRequest(res, *hostPtr, listener, flags, af);
|
||||
new nsDNSAsyncRequest(res, hostname, listener, flags, af);
|
||||
if (!req)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
NS_ADDREF(*result = req);
|
||||
|
||||
MOZ_EVENT_TRACER_NAME_OBJECT(req, hostname.BeginReading());
|
||||
MOZ_EVENT_TRACER_NAME_OBJECT(req, aHostname.BeginReading());
|
||||
MOZ_EVENT_TRACER_WAIT(req, "net::dns::lookup");
|
||||
|
||||
// addref for resolver; will be released when OnLookupComplete is called.
|
||||
NS_ADDREF(req);
|
||||
rv = res->ResolveHost(req->mHost.get(), flags, af, req);
|
||||
nsresult rv = res->ResolveHost(req->mHost.get(), flags, af, req);
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_RELEASE(req);
|
||||
NS_RELEASE(*result);
|
||||
|
@ -745,6 +745,7 @@ nsDNSService::CancelAsyncResolve(const nsACString &aHostname,
|
|||
// simultaneous shutdown!!
|
||||
nsRefPtr<nsHostResolver> res;
|
||||
nsCOMPtr<nsIIDNService> idn;
|
||||
bool localDomain = false;
|
||||
{
|
||||
MutexAutoLock lock(mLock);
|
||||
|
||||
|
@ -753,21 +754,14 @@ nsDNSService::CancelAsyncResolve(const nsACString &aHostname,
|
|||
|
||||
res = mResolver;
|
||||
idn = mIDN;
|
||||
localDomain = mLocalDomains.GetEntry(aHostname);
|
||||
}
|
||||
if (!res)
|
||||
return NS_ERROR_OFFLINE;
|
||||
|
||||
nsCString hostname(aHostname);
|
||||
|
||||
nsAutoCString hostACE;
|
||||
if (idn && !IsASCII(aHostname)) {
|
||||
if (IsUTF8(aHostname) &&
|
||||
NS_SUCCEEDED(idn->ConvertUTF8toACE(aHostname, hostACE))) {
|
||||
hostname = hostACE;
|
||||
} else {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
}
|
||||
nsCString hostname;
|
||||
if (!PreprocessHostname(localDomain, aHostname, idn, hostname))
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
uint16_t af = GetAFForLookup(hostname, aFlags);
|
||||
|
||||
|
@ -776,7 +770,7 @@ nsDNSService::CancelAsyncResolve(const nsACString &aHostname,
|
|||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDNSService::Resolve(const nsACString &hostname,
|
||||
nsDNSService::Resolve(const nsACString &aHostname,
|
||||
uint32_t flags,
|
||||
nsIDNSRecord **result)
|
||||
{
|
||||
|
@ -789,12 +783,12 @@ nsDNSService::Resolve(const nsACString &hostname,
|
|||
MutexAutoLock lock(mLock);
|
||||
res = mResolver;
|
||||
idn = mIDN;
|
||||
localDomain = mLocalDomains.GetEntry(hostname);
|
||||
localDomain = mLocalDomains.GetEntry(aHostname);
|
||||
}
|
||||
|
||||
if (mNotifyResolution) {
|
||||
NS_DispatchToMainThread(new NotifyDNSResolution(mObserverService,
|
||||
hostname));
|
||||
aHostname));
|
||||
}
|
||||
|
||||
NS_ENSURE_TRUE(res, NS_ERROR_OFFLINE);
|
||||
|
@ -802,23 +796,9 @@ nsDNSService::Resolve(const nsACString &hostname,
|
|||
if (mOffline)
|
||||
flags |= RESOLVE_OFFLINE;
|
||||
|
||||
const nsACString *hostPtr = &hostname;
|
||||
|
||||
nsAutoCString strLocalhost(NS_LITERAL_CSTRING("localhost"));
|
||||
if (localDomain) {
|
||||
hostPtr = &strLocalhost;
|
||||
}
|
||||
|
||||
nsresult rv;
|
||||
nsAutoCString hostACE;
|
||||
if (idn && !IsASCII(*hostPtr)) {
|
||||
if (IsUTF8(*hostPtr) &&
|
||||
NS_SUCCEEDED(idn->ConvertUTF8toACE(*hostPtr, hostACE))) {
|
||||
hostPtr = &hostACE;
|
||||
} else {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
}
|
||||
nsCString hostname;
|
||||
if (!PreprocessHostname(localDomain, aHostname, idn, hostname))
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
//
|
||||
// sync resolve: since the host resolver only works asynchronously, we need
|
||||
|
@ -835,9 +815,9 @@ nsDNSService::Resolve(const nsACString &hostname,
|
|||
PR_EnterMonitor(mon);
|
||||
nsDNSSyncRequest syncReq(mon);
|
||||
|
||||
uint16_t af = GetAFForLookup(*hostPtr, flags);
|
||||
uint16_t af = GetAFForLookup(hostname, flags);
|
||||
|
||||
rv = res->ResolveHost(PromiseFlatCString(*hostPtr).get(), flags, af, &syncReq);
|
||||
nsresult rv = res->ResolveHost(hostname.get(), flags, af, &syncReq);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
// wait for result
|
||||
while (!syncReq.mDone)
|
||||
|
|
|
@ -668,6 +668,9 @@ class TreeMetadataEmitter(LoggingMixin):
|
|||
shared_lib = True
|
||||
shared_args['variant'] = SharedLibrary.FRAMEWORK
|
||||
|
||||
if not static_lib and not shared_lib:
|
||||
static_lib = True
|
||||
|
||||
if static_name:
|
||||
if not static_lib:
|
||||
raise SandboxValidationError(
|
||||
|
@ -688,9 +691,6 @@ class TreeMetadataEmitter(LoggingMixin):
|
|||
'SONAME requires FORCE_SHARED_LIB', context)
|
||||
shared_args['soname'] = soname
|
||||
|
||||
if not static_lib and not shared_lib:
|
||||
static_lib = True
|
||||
|
||||
# If both a shared and a static library are created, only the
|
||||
# shared library is meant to be a SDK library.
|
||||
if context.get('SDK_LIBRARY'):
|
||||
|
|
|
@ -152,7 +152,7 @@ GetOCSPResponseForType(OCSPResponseType aORT, CERTCertificate *aCert,
|
|||
if (aORT == ORTExpired || aORT == ORTExpiredFreshCA ||
|
||||
aORT == ORTRevokedOld || aORT == ORTUnknownOld) {
|
||||
context.thisUpdate = oldNow;
|
||||
context.nextUpdate = oldNow + 10;
|
||||
context.nextUpdate = oldNow + Time::ONE_DAY_IN_SECONDS;
|
||||
}
|
||||
if (aORT == ORTLongValidityAlmostExpired) {
|
||||
context.thisUpdate = now - (320 * Time::ONE_DAY_IN_SECONDS);
|
||||
|
|
|
@ -40,8 +40,6 @@ static ByteString
|
|||
CreateCert(const char* issuerCN,
|
||||
const char* subjectCN,
|
||||
EndEntityOrCA endEntityOrCA,
|
||||
/*optional*/ TestKeyPair* issuerKey,
|
||||
/*out*/ ScopedTestKeyPair& subjectKey,
|
||||
/*out*/ ScopedCERTCertificate* subjectCert = nullptr)
|
||||
{
|
||||
static long serialNumberValue = 0;
|
||||
|
@ -60,13 +58,12 @@ CreateCert(const char* issuerCN,
|
|||
EXPECT_FALSE(ENCODING_FAILED(extensions[0]));
|
||||
}
|
||||
|
||||
ScopedTestKeyPair reusedKey(CloneReusedKeyPair());
|
||||
ByteString certDER(CreateEncodedCertificate(
|
||||
v3, sha256WithRSAEncryption,
|
||||
serialNumber, issuerDER,
|
||||
oneDayBeforeNow, oneDayAfterNow,
|
||||
subjectDER, extensions, issuerKey,
|
||||
sha256WithRSAEncryption,
|
||||
subjectKey));
|
||||
v3, sha256WithRSAEncryption, serialNumber, issuerDER,
|
||||
oneDayBeforeNow, oneDayAfterNow, subjectDER,
|
||||
*reusedKey, extensions, *reusedKey,
|
||||
sha256WithRSAEncryption));
|
||||
EXPECT_FALSE(ENCODING_FAILED(certDER));
|
||||
if (subjectCert) {
|
||||
SECItem certDERItem = {
|
||||
|
@ -100,7 +97,7 @@ public:
|
|||
for (size_t i = 0; i < MOZILLA_PKIX_ARRAY_LENGTH(names); ++i) {
|
||||
const char* issuerName = i == 0 ? names[0] : names[i-1];
|
||||
(void) CreateCert(issuerName, names[i], EndEntityOrCA::MustBeCA,
|
||||
leafCAKey.get(), leafCAKey, &certChainTail[i]);
|
||||
&certChainTail[i]);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -192,7 +189,6 @@ private:
|
|||
ScopedCERTCertificate certChainTail[7];
|
||||
|
||||
public:
|
||||
ScopedTestKeyPair leafCAKey;
|
||||
CERTCertificate* GetLeafCACert() const
|
||||
{
|
||||
return certChainTail[MOZILLA_PKIX_ARRAY_LENGTH(certChainTail) - 1].get();
|
||||
|
@ -238,11 +234,9 @@ TEST_F(pkixbuild, MaxAcceptableCertChainLength)
|
|||
}
|
||||
|
||||
{
|
||||
ScopedTestKeyPair unusedKeyPair;
|
||||
ScopedCERTCertificate cert;
|
||||
ByteString certDER(CreateCert("CA7", "Direct End-Entity",
|
||||
EndEntityOrCA::MustBeEndEntity,
|
||||
trustDomain.leafCAKey.get(), unusedKeyPair));
|
||||
EndEntityOrCA::MustBeEndEntity));
|
||||
ASSERT_FALSE(ENCODING_FAILED(certDER));
|
||||
Input certDERInput;
|
||||
ASSERT_EQ(Success, certDERInput.Init(certDER.data(), certDER.length()));
|
||||
|
@ -259,7 +253,6 @@ TEST_F(pkixbuild, MaxAcceptableCertChainLength)
|
|||
TEST_F(pkixbuild, BeyondMaxAcceptableCertChainLength)
|
||||
{
|
||||
static char const* const caCertName = "CA Too Far";
|
||||
ScopedTestKeyPair caKeyPair;
|
||||
|
||||
// We need a CERTCertificate for caCert so that the trustdomain's FindIssuer
|
||||
// method can find it through the NSS cert DB.
|
||||
|
@ -267,7 +260,6 @@ TEST_F(pkixbuild, BeyondMaxAcceptableCertChainLength)
|
|||
|
||||
{
|
||||
ByteString certDER(CreateCert("CA7", caCertName, EndEntityOrCA::MustBeCA,
|
||||
trustDomain.leafCAKey.get(), caKeyPair,
|
||||
&caCert));
|
||||
ASSERT_FALSE(ENCODING_FAILED(certDER));
|
||||
Input certDERInput;
|
||||
|
@ -282,10 +274,8 @@ TEST_F(pkixbuild, BeyondMaxAcceptableCertChainLength)
|
|||
}
|
||||
|
||||
{
|
||||
ScopedTestKeyPair unusedKeyPair;
|
||||
ByteString certDER(CreateCert(caCertName, "End-Entity Too Far",
|
||||
EndEntityOrCA::MustBeEndEntity,
|
||||
caKeyPair.get(), unusedKeyPair));
|
||||
EndEntityOrCA::MustBeEndEntity));
|
||||
ASSERT_FALSE(ENCODING_FAILED(certDER));
|
||||
Input certDERInput;
|
||||
ASSERT_EQ(Success, certDERInput.Init(certDER.data(), certDER.length()));
|
||||
|
@ -383,9 +373,8 @@ private:
|
|||
TEST_F(pkixbuild, NoRevocationCheckingForExpiredCert)
|
||||
{
|
||||
const char* rootCN = "Root CA";
|
||||
ScopedTestKeyPair rootKey;
|
||||
ByteString rootDER(CreateCert(rootCN, rootCN, EndEntityOrCA::MustBeCA,
|
||||
nullptr, rootKey, nullptr));
|
||||
nullptr));
|
||||
EXPECT_FALSE(ENCODING_FAILED(rootDER));
|
||||
ExpiredCertTrustDomain expiredCertTrustDomain(rootDER);
|
||||
|
||||
|
@ -393,15 +382,14 @@ TEST_F(pkixbuild, NoRevocationCheckingForExpiredCert)
|
|||
EXPECT_FALSE(ENCODING_FAILED(serialNumber));
|
||||
ByteString issuerDER(CNToDERName(rootCN));
|
||||
ByteString subjectDER(CNToDERName("Expired End-Entity Cert"));
|
||||
ScopedTestKeyPair unusedSubjectKey;
|
||||
ScopedTestKeyPair reusedKey(CloneReusedKeyPair());
|
||||
ByteString certDER(CreateEncodedCertificate(
|
||||
v3, sha256WithRSAEncryption,
|
||||
serialNumber, issuerDER,
|
||||
oneDayBeforeNow - Time::ONE_DAY_IN_SECONDS,
|
||||
oneDayBeforeNow,
|
||||
subjectDER, nullptr, rootKey.get(),
|
||||
sha256WithRSAEncryption,
|
||||
unusedSubjectKey));
|
||||
subjectDER, *reusedKey, nullptr, *reusedKey,
|
||||
sha256WithRSAEncryption));
|
||||
EXPECT_FALSE(ENCODING_FAILED(certDER));
|
||||
|
||||
Input cert;
|
||||
|
|
|
@ -31,9 +31,8 @@ using namespace mozilla::pkix::test;
|
|||
|
||||
// Creates a self-signed certificate with the given extension.
|
||||
static ByteString
|
||||
CreateCert(const char* subjectCN,
|
||||
const ByteString* extensions, // empty-string-terminated array
|
||||
/*out*/ ScopedTestKeyPair& subjectKey)
|
||||
CreateCertWithExtensions(const char* subjectCN,
|
||||
const ByteString* extensions)
|
||||
{
|
||||
static long serialNumberValue = 0;
|
||||
++serialNumberValue;
|
||||
|
@ -43,23 +42,21 @@ CreateCert(const char* subjectCN,
|
|||
EXPECT_FALSE(ENCODING_FAILED(issuerDER));
|
||||
ByteString subjectDER(CNToDERName(subjectCN));
|
||||
EXPECT_FALSE(ENCODING_FAILED(subjectDER));
|
||||
ScopedTestKeyPair subjectKey(CloneReusedKeyPair());
|
||||
return CreateEncodedCertificate(v3, sha256WithRSAEncryption,
|
||||
serialNumber, issuerDER,
|
||||
oneDayBeforeNow, oneDayAfterNow,
|
||||
subjectDER, extensions,
|
||||
nullptr,
|
||||
sha256WithRSAEncryption,
|
||||
subjectKey);
|
||||
subjectDER, *subjectKey, extensions,
|
||||
*subjectKey,
|
||||
sha256WithRSAEncryption);
|
||||
}
|
||||
|
||||
// Creates a self-signed certificate with the given extension.
|
||||
static ByteString
|
||||
CreateCert(const char* subjectStr,
|
||||
const ByteString& extension,
|
||||
/*out*/ ScopedTestKeyPair& subjectKey)
|
||||
CreateCertWithOneExtension(const char* subjectStr, const ByteString& extension)
|
||||
{
|
||||
const ByteString extensions[] = { extension, ByteString() };
|
||||
return CreateCert(subjectStr, extensions, subjectKey);
|
||||
return CreateCertWithExtensions(subjectStr, extensions);
|
||||
}
|
||||
|
||||
class TrustEverythingTrustDomain : public TrustDomain
|
||||
|
@ -136,8 +133,7 @@ TEST_F(pkixcert_extension, UnknownCriticalExtension)
|
|||
unknownCriticalExtension(unknownCriticalExtensionBytes,
|
||||
sizeof(unknownCriticalExtensionBytes));
|
||||
const char* certCN = "Cert With Unknown Critical Extension";
|
||||
ScopedTestKeyPair key;
|
||||
ByteString cert(CreateCert(certCN, unknownCriticalExtension, key));
|
||||
ByteString cert(CreateCertWithOneExtension(certCN, unknownCriticalExtension));
|
||||
ASSERT_FALSE(ENCODING_FAILED(cert));
|
||||
Input certInput;
|
||||
ASSERT_EQ(Success, certInput.Init(cert.data(), cert.length()));
|
||||
|
@ -166,8 +162,8 @@ TEST_F(pkixcert_extension, UnknownNonCriticalExtension)
|
|||
unknownNonCriticalExtension(unknownNonCriticalExtensionBytes,
|
||||
sizeof(unknownNonCriticalExtensionBytes));
|
||||
const char* certCN = "Cert With Unknown NonCritical Extension";
|
||||
ScopedTestKeyPair key;
|
||||
ByteString cert(CreateCert(certCN, unknownNonCriticalExtension, key));
|
||||
ByteString cert(CreateCertWithOneExtension(certCN,
|
||||
unknownNonCriticalExtension));
|
||||
ASSERT_FALSE(ENCODING_FAILED(cert));
|
||||
Input certInput;
|
||||
ASSERT_EQ(Success, certInput.Init(cert.data(), cert.length()));
|
||||
|
@ -197,8 +193,8 @@ TEST_F(pkixcert_extension, WrongOIDCriticalExtension)
|
|||
wrongOIDCriticalExtension(wrongOIDCriticalExtensionBytes,
|
||||
sizeof(wrongOIDCriticalExtensionBytes));
|
||||
const char* certCN = "Cert With Critical Wrong OID Extension";
|
||||
ScopedTestKeyPair key;
|
||||
ByteString cert(CreateCert(certCN, wrongOIDCriticalExtension, key));
|
||||
ByteString cert(CreateCertWithOneExtension(certCN,
|
||||
wrongOIDCriticalExtension));
|
||||
ASSERT_FALSE(ENCODING_FAILED(cert));
|
||||
Input certInput;
|
||||
ASSERT_EQ(Success, certInput.Init(cert.data(), cert.length()));
|
||||
|
@ -230,8 +226,7 @@ TEST_F(pkixcert_extension, CriticalAIAExtension)
|
|||
criticalAIAExtension(criticalAIAExtensionBytes,
|
||||
sizeof(criticalAIAExtensionBytes));
|
||||
const char* certCN = "Cert With Critical AIA Extension";
|
||||
ScopedTestKeyPair key;
|
||||
ByteString cert(CreateCert(certCN, criticalAIAExtension, key));
|
||||
ByteString cert(CreateCertWithOneExtension(certCN, criticalAIAExtension));
|
||||
ASSERT_FALSE(ENCODING_FAILED(cert));
|
||||
Input certInput;
|
||||
ASSERT_EQ(Success, certInput.Init(cert.data(), cert.length()));
|
||||
|
@ -260,8 +255,8 @@ TEST_F(pkixcert_extension, UnknownCriticalCEExtension)
|
|||
unknownCriticalCEExtension(unknownCriticalCEExtensionBytes,
|
||||
sizeof(unknownCriticalCEExtensionBytes));
|
||||
const char* certCN = "Cert With Unknown Critical id-ce Extension";
|
||||
ScopedTestKeyPair key;
|
||||
ByteString cert(CreateCert(certCN, unknownCriticalCEExtension, key));
|
||||
ByteString cert(CreateCertWithOneExtension(certCN,
|
||||
unknownCriticalCEExtension));
|
||||
ASSERT_FALSE(ENCODING_FAILED(cert));
|
||||
Input certInput;
|
||||
ASSERT_EQ(Success, certInput.Init(cert.data(), cert.length()));
|
||||
|
@ -290,8 +285,7 @@ TEST_F(pkixcert_extension, KnownCriticalCEExtension)
|
|||
criticalCEExtension(criticalCEExtensionBytes,
|
||||
sizeof(criticalCEExtensionBytes));
|
||||
const char* certCN = "Cert With Known Critical id-ce Extension";
|
||||
ScopedTestKeyPair key;
|
||||
ByteString cert(CreateCert(certCN, criticalCEExtension, key));
|
||||
ByteString cert(CreateCertWithOneExtension(certCN, criticalCEExtension));
|
||||
ASSERT_FALSE(ENCODING_FAILED(cert));
|
||||
Input certInput;
|
||||
ASSERT_EQ(Success, certInput.Init(cert.data(), cert.length()));
|
||||
|
@ -319,8 +313,7 @@ TEST_F(pkixcert_extension, DuplicateSubjectAltName)
|
|||
static const ByteString DER(DER_BYTES, sizeof(DER_BYTES));
|
||||
static const ByteString extensions[] = { DER, DER, ByteString() };
|
||||
static const char* certCN = "Cert With Duplicate subjectAltName";
|
||||
ScopedTestKeyPair key;
|
||||
ByteString cert(CreateCert(certCN, extensions, key));
|
||||
ByteString cert(CreateCertWithExtensions(certCN, extensions));
|
||||
ASSERT_FALSE(ENCODING_FAILED(cert));
|
||||
Input certInput;
|
||||
ASSERT_EQ(Success, certInput.Init(cert.data(), cert.length()));
|
||||
|
|
|
@ -16,8 +16,6 @@ CreateCert(const char* issuerCN,
|
|||
const char* subjectCN,
|
||||
EndEntityOrCA endEntityOrCA,
|
||||
const ByteString& signatureAlgorithm,
|
||||
/*optional*/ TestKeyPair* issuerKey,
|
||||
/*out*/ ScopedTestKeyPair& subjectKey,
|
||||
/*out*/ ByteString& subjectDER)
|
||||
{
|
||||
static long serialNumberValue = 0;
|
||||
|
@ -38,12 +36,13 @@ CreateCert(const char* issuerCN,
|
|||
EXPECT_FALSE(ENCODING_FAILED(extensions[0]));
|
||||
}
|
||||
|
||||
ScopedTestKeyPair reusedKey(CloneReusedKeyPair());
|
||||
ByteString certDER(CreateEncodedCertificate(v3, signatureAlgorithm,
|
||||
serialNumber,
|
||||
issuerDER, oneDayBeforeNow,
|
||||
oneDayAfterNow, subjectDER,
|
||||
extensions, issuerKey,
|
||||
signatureAlgorithm, subjectKey));
|
||||
serialNumber, issuerDER,
|
||||
oneDayBeforeNow, oneDayAfterNow,
|
||||
subjectDER, *reusedKey,
|
||||
extensions, *reusedKey,
|
||||
signatureAlgorithm));
|
||||
EXPECT_FALSE(ENCODING_FAILED(certDER));
|
||||
return certDER;
|
||||
}
|
||||
|
@ -206,31 +205,26 @@ TEST_P(pkixcert_IsValidChainForAlgorithm, IsValidChainForAlgorithm)
|
|||
{
|
||||
const ChainValidity& chainValidity(GetParam());
|
||||
const char* rootCN = "CN=Root";
|
||||
ScopedTestKeyPair rootKey;
|
||||
ByteString rootSubjectDER;
|
||||
ByteString rootEncoded(
|
||||
CreateCert(rootCN, rootCN, EndEntityOrCA::MustBeCA,
|
||||
chainValidity.rootSignatureAlgorithm,
|
||||
nullptr, rootKey, rootSubjectDER));
|
||||
chainValidity.rootSignatureAlgorithm, rootSubjectDER));
|
||||
EXPECT_FALSE(ENCODING_FAILED(rootEncoded));
|
||||
EXPECT_FALSE(ENCODING_FAILED(rootSubjectDER));
|
||||
|
||||
const char* issuerCN = rootCN;
|
||||
TestKeyPair* issuerKey = rootKey.get();
|
||||
|
||||
const char* intermediateCN = "CN=Intermediate";
|
||||
ScopedTestKeyPair intermediateKey;
|
||||
ByteString intermediateSubjectDER;
|
||||
ByteString intermediateEncoded;
|
||||
if (chainValidity.optionalIntermediateSignatureAlgorithm != NO_INTERMEDIATE) {
|
||||
intermediateEncoded =
|
||||
CreateCert(rootCN, intermediateCN, EndEntityOrCA::MustBeCA,
|
||||
chainValidity.optionalIntermediateSignatureAlgorithm,
|
||||
rootKey.get(), intermediateKey, intermediateSubjectDER);
|
||||
intermediateSubjectDER);
|
||||
EXPECT_FALSE(ENCODING_FAILED(intermediateEncoded));
|
||||
EXPECT_FALSE(ENCODING_FAILED(intermediateSubjectDER));
|
||||
issuerCN = intermediateCN;
|
||||
issuerKey = intermediateKey.get();
|
||||
}
|
||||
|
||||
AlgorithmTestsTrustDomain trustDomain(rootEncoded, rootSubjectDER,
|
||||
|
@ -238,12 +232,11 @@ TEST_P(pkixcert_IsValidChainForAlgorithm, IsValidChainForAlgorithm)
|
|||
intermediateSubjectDER);
|
||||
|
||||
const char* endEntityCN = "CN=End Entity";
|
||||
ScopedTestKeyPair endEntityKey;
|
||||
ByteString endEntitySubjectDER;
|
||||
ByteString endEntityEncoded(
|
||||
CreateCert(issuerCN, endEntityCN, EndEntityOrCA::MustBeEndEntity,
|
||||
chainValidity.endEntitySignatureAlgorithm,
|
||||
issuerKey, endEntityKey, endEntitySubjectDER));
|
||||
endEntitySubjectDER));
|
||||
EXPECT_FALSE(ENCODING_FAILED(endEntityEncoded));
|
||||
EXPECT_FALSE(ENCODING_FAILED(endEntitySubjectDER));
|
||||
|
||||
|
|
|
@ -423,13 +423,13 @@ protected:
|
|||
: ByteString(),
|
||||
ByteString()
|
||||
};
|
||||
ScopedTestKeyPair signerKeyPair;
|
||||
ScopedTestKeyPair signerKeyPair(GenerateKeyPair());
|
||||
ByteString signerDER(CreateEncodedCertificate(
|
||||
++rootIssuedCount, rootName,
|
||||
oneDayBeforeNow, oneDayAfterNow, certSubjectName,
|
||||
certSignatureAlgorithm,
|
||||
++rootIssuedCount, certSignatureAlgorithm,
|
||||
rootName, oneDayBeforeNow, oneDayAfterNow,
|
||||
certSubjectName, *signerKeyPair,
|
||||
signerEKUDER ? extensions : nullptr,
|
||||
rootKeyPair.get(), signerKeyPair));
|
||||
*rootKeyPair));
|
||||
EXPECT_FALSE(ENCODING_FAILED(signerDER));
|
||||
if (signerDEROut) {
|
||||
*signerDEROut = signerDER;
|
||||
|
@ -451,14 +451,14 @@ protected:
|
|||
}
|
||||
|
||||
static ByteString CreateEncodedCertificate(uint32_t serialNumber,
|
||||
const ByteString& signatureAlg,
|
||||
const char* issuer,
|
||||
time_t notBefore,
|
||||
time_t notAfter,
|
||||
const char* subject,
|
||||
const ByteString& signatureAlg,
|
||||
const TestKeyPair& subjectKeyPair,
|
||||
/*optional*/ const ByteString* extensions,
|
||||
/*optional*/ TestKeyPair* signerKeyPair,
|
||||
/*out*/ ScopedTestKeyPair& keyPair)
|
||||
const TestKeyPair& signerKeyPair)
|
||||
{
|
||||
ByteString serialNumberDER(CreateEncodedSerialNumber(serialNumber));
|
||||
if (ENCODING_FAILED(serialNumberDER)) {
|
||||
|
@ -473,13 +473,10 @@ protected:
|
|||
return ByteString();
|
||||
}
|
||||
return ::mozilla::pkix::test::CreateEncodedCertificate(
|
||||
v3,
|
||||
signatureAlg,
|
||||
serialNumberDER, issuerDER, notBefore,
|
||||
notAfter, subjectDER, extensions,
|
||||
signerKeyPair,
|
||||
signatureAlg,
|
||||
keyPair);
|
||||
v3, signatureAlg, serialNumberDER,
|
||||
issuerDER, notBefore, notAfter,
|
||||
subjectDER, subjectKeyPair, extensions,
|
||||
signerKeyPair, signatureAlg);
|
||||
}
|
||||
|
||||
static const Input OCSPSigningEKUDER;
|
||||
|
@ -577,13 +574,13 @@ TEST_F(pkixocsp_VerifyEncodedResponse_DelegatedResponder, good_expired)
|
|||
ByteString()
|
||||
};
|
||||
|
||||
ScopedTestKeyPair signerKeyPair;
|
||||
ScopedTestKeyPair signerKeyPair(GenerateKeyPair());
|
||||
ByteString signerDER(CreateEncodedCertificate(
|
||||
++rootIssuedCount, rootName,
|
||||
++rootIssuedCount, sha256WithRSAEncryption, rootName,
|
||||
now - (10 * Time::ONE_DAY_IN_SECONDS),
|
||||
now - (2 * Time::ONE_DAY_IN_SECONDS),
|
||||
signerName, sha256WithRSAEncryption, extensions,
|
||||
rootKeyPair.get(), signerKeyPair));
|
||||
signerName, *signerKeyPair, extensions,
|
||||
*rootKeyPair));
|
||||
ASSERT_FALSE(ENCODING_FAILED(signerDER));
|
||||
|
||||
ByteString certs[] = { signerDER, ByteString() };
|
||||
|
@ -613,13 +610,14 @@ TEST_F(pkixocsp_VerifyEncodedResponse_DelegatedResponder, good_future)
|
|||
ByteString()
|
||||
};
|
||||
|
||||
ScopedTestKeyPair signerKeyPair;
|
||||
ScopedTestKeyPair signerKeyPair(GenerateKeyPair());
|
||||
ByteString signerDER(CreateEncodedCertificate(
|
||||
++rootIssuedCount, rootName,
|
||||
++rootIssuedCount, sha256WithRSAEncryption,
|
||||
rootName,
|
||||
now + (2 * Time::ONE_DAY_IN_SECONDS),
|
||||
now + (10 * Time::ONE_DAY_IN_SECONDS),
|
||||
signerName, sha256WithRSAEncryption, extensions,
|
||||
rootKeyPair.get(), signerKeyPair));
|
||||
signerName, *signerKeyPair, extensions,
|
||||
*rootKeyPair));
|
||||
ASSERT_FALSE(ENCODING_FAILED(signerDER));
|
||||
|
||||
ByteString certs[] = { signerDER, ByteString() };
|
||||
|
@ -719,11 +717,11 @@ TEST_F(pkixocsp_VerifyEncodedResponse_DelegatedResponder, good_unknown_issuer)
|
|||
ExtensionCriticality::NotCritical),
|
||||
ByteString()
|
||||
};
|
||||
ScopedTestKeyPair signerKeyPair;
|
||||
ScopedTestKeyPair signerKeyPair(GenerateKeyPair());
|
||||
ByteString signerDER(CreateEncodedCertificate(
|
||||
1, subCAName, oneDayBeforeNow, oneDayAfterNow,
|
||||
signerName, sha256WithRSAEncryption, extensions,
|
||||
unknownKeyPair.get(), signerKeyPair));
|
||||
1, sha256WithRSAEncryption, subCAName,
|
||||
oneDayBeforeNow, oneDayAfterNow, signerName,
|
||||
*signerKeyPair, extensions, *unknownKeyPair));
|
||||
ASSERT_FALSE(ENCODING_FAILED(signerDER));
|
||||
|
||||
// OCSP response signed by that delegated responder
|
||||
|
@ -759,12 +757,11 @@ TEST_F(pkixocsp_VerifyEncodedResponse_DelegatedResponder,
|
|||
CreateEncodedBasicConstraints(true, 0, ExtensionCriticality::NotCritical),
|
||||
ByteString()
|
||||
};
|
||||
ScopedTestKeyPair subCAKeyPair;
|
||||
ScopedTestKeyPair subCAKeyPair(GenerateKeyPair());
|
||||
ByteString subCADER(CreateEncodedCertificate(
|
||||
++rootIssuedCount, rootName,
|
||||
oneDayBeforeNow, oneDayAfterNow,
|
||||
subCAName, sha256WithRSAEncryption,
|
||||
subCAExtensions, rootKeyPair.get(), subCAKeyPair));
|
||||
++rootIssuedCount, sha256WithRSAEncryption, rootName,
|
||||
oneDayBeforeNow, oneDayAfterNow, subCAName,
|
||||
*subCAKeyPair, subCAExtensions, *rootKeyPair));
|
||||
ASSERT_FALSE(ENCODING_FAILED(subCADER));
|
||||
|
||||
// Delegated responder cert signed by that sub-CA
|
||||
|
@ -773,11 +770,11 @@ TEST_F(pkixocsp_VerifyEncodedResponse_DelegatedResponder,
|
|||
ExtensionCriticality::NotCritical),
|
||||
ByteString(),
|
||||
};
|
||||
ScopedTestKeyPair signerKeyPair;
|
||||
ScopedTestKeyPair signerKeyPair(GenerateKeyPair());
|
||||
ByteString signerDER(CreateEncodedCertificate(
|
||||
1, subCAName, oneDayBeforeNow, oneDayAfterNow,
|
||||
signerName, sha256WithRSAEncryption, extensions,
|
||||
subCAKeyPair.get(), signerKeyPair));
|
||||
1, sha256WithRSAEncryption, subCAName,
|
||||
oneDayBeforeNow, oneDayAfterNow, signerName,
|
||||
*signerKeyPair, extensions, *subCAKeyPair));
|
||||
ASSERT_FALSE(ENCODING_FAILED(signerDER));
|
||||
|
||||
// OCSP response signed by the delegated responder issued by the sub-CA
|
||||
|
@ -814,14 +811,13 @@ TEST_F(pkixocsp_VerifyEncodedResponse_DelegatedResponder,
|
|||
CreateEncodedBasicConstraints(true, 0, ExtensionCriticality::NotCritical),
|
||||
ByteString()
|
||||
};
|
||||
ScopedTestKeyPair subCAKeyPair;
|
||||
ByteString subCADER(CreateEncodedCertificate(++rootIssuedCount, rootName,
|
||||
oneDayBeforeNow, oneDayAfterNow,
|
||||
subCAName,
|
||||
ScopedTestKeyPair subCAKeyPair(GenerateKeyPair());
|
||||
ByteString subCADER(CreateEncodedCertificate(++rootIssuedCount,
|
||||
sha256WithRSAEncryption,
|
||||
subCAExtensions,
|
||||
rootKeyPair.get(),
|
||||
subCAKeyPair));
|
||||
rootName,
|
||||
oneDayBeforeNow, oneDayAfterNow,
|
||||
subCAName, *subCAKeyPair,
|
||||
subCAExtensions, *rootKeyPair));
|
||||
ASSERT_FALSE(ENCODING_FAILED(subCADER));
|
||||
|
||||
// Delegated responder cert signed by that sub-CA
|
||||
|
@ -830,11 +826,11 @@ TEST_F(pkixocsp_VerifyEncodedResponse_DelegatedResponder,
|
|||
ExtensionCriticality::NotCritical),
|
||||
ByteString()
|
||||
};
|
||||
ScopedTestKeyPair signerKeyPair;
|
||||
ScopedTestKeyPair signerKeyPair(GenerateKeyPair());
|
||||
ByteString signerDER(CreateEncodedCertificate(
|
||||
1, subCAName, oneDayBeforeNow, oneDayAfterNow,
|
||||
signerName, sha256WithRSAEncryption, extensions,
|
||||
subCAKeyPair.get(), signerKeyPair));
|
||||
1, sha256WithRSAEncryption, subCAName,
|
||||
oneDayBeforeNow, oneDayAfterNow, signerName,
|
||||
*signerKeyPair, extensions, *subCAKeyPair));
|
||||
ASSERT_FALSE(ENCODING_FAILED(signerDER));
|
||||
|
||||
// OCSP response signed by the delegated responder issued by the sub-CA
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
#include "pk11pub.h"
|
||||
#include "pkix/pkixnss.h"
|
||||
#include "pkixder.h"
|
||||
#include "prinit.h"
|
||||
#include "secerr.h"
|
||||
#include "secitem.h"
|
||||
|
||||
|
@ -52,13 +53,24 @@ SECITEM_FreeItem_true(SECItem* item)
|
|||
|
||||
typedef mozilla::pkix::ScopedPtr<SECItem, SECITEM_FreeItem_true> ScopedSECItem;
|
||||
|
||||
Result
|
||||
TestKeyPair* GenerateKeyPairInner();
|
||||
|
||||
void
|
||||
InitNSSIfNeeded()
|
||||
{
|
||||
if (NSS_NoDB_Init(nullptr) != SECSuccess) {
|
||||
return MapPRErrorCodeToResult(PR_GetError());
|
||||
abort();
|
||||
}
|
||||
return Success;
|
||||
}
|
||||
|
||||
static ScopedTestKeyPair reusedKeyPair;
|
||||
|
||||
PRStatus
|
||||
InitReusedKeyPair()
|
||||
{
|
||||
InitNSSIfNeeded();
|
||||
reusedKeyPair = GenerateKeyPairInner();
|
||||
return reusedKeyPair ? PR_SUCCESS : PR_FAILURE;
|
||||
}
|
||||
|
||||
class NSSTestKeyPair : public TestKeyPair
|
||||
|
@ -142,16 +154,14 @@ TestKeyPair* CreateTestKeyPair(const ByteString& spki,
|
|||
return new (std::nothrow) NSSTestKeyPair(spki, spk, privateKey);
|
||||
}
|
||||
|
||||
TestKeyPair*
|
||||
GenerateKeyPair()
|
||||
{
|
||||
if (InitNSSIfNeeded() != Success) {
|
||||
return nullptr;
|
||||
}
|
||||
namespace {
|
||||
|
||||
TestKeyPair*
|
||||
GenerateKeyPairInner()
|
||||
{
|
||||
ScopedPtr<PK11SlotInfo, PK11_FreeSlot> slot(PK11_GetInternalSlot());
|
||||
if (!slot) {
|
||||
return nullptr;
|
||||
abort();
|
||||
}
|
||||
|
||||
// Bug 1012786: PK11_GenerateKeyPair can fail if there is insufficient
|
||||
|
@ -171,12 +181,12 @@ GenerateKeyPair()
|
|||
ScopedSECItem
|
||||
spkiDER(SECKEY_EncodeDERSubjectPublicKeyInfo(publicKey.get()));
|
||||
if (!spkiDER) {
|
||||
return nullptr;
|
||||
break;
|
||||
}
|
||||
ScopedPtr<CERTSubjectPublicKeyInfo, SECKEY_DestroySubjectPublicKeyInfo>
|
||||
spki(SECKEY_CreateSubjectPublicKeyInfo(publicKey.get()));
|
||||
if (!spki) {
|
||||
return nullptr;
|
||||
break;
|
||||
}
|
||||
SECItem spkDER = spki->subjectPublicKey;
|
||||
DER_ConvertBitString(&spkDER); // bits to bytes
|
||||
|
@ -201,15 +211,40 @@ GenerateKeyPair()
|
|||
}
|
||||
}
|
||||
|
||||
abort();
|
||||
#if defined(_MSC_VER) && (_MSC_VER < 1700)
|
||||
// Older versions of MSVC don't know that abort() never returns, so silence
|
||||
// its warning by adding a redundant and never-reached return. But, only do
|
||||
// it for that ancient compiler, because some other compilers will rightly
|
||||
// warn that the return statement is unreachable.
|
||||
return nullptr;
|
||||
#endif
|
||||
}
|
||||
|
||||
} // unnamed namespace
|
||||
|
||||
TestKeyPair*
|
||||
GenerateKeyPair()
|
||||
{
|
||||
InitNSSIfNeeded();
|
||||
return GenerateKeyPairInner();
|
||||
}
|
||||
|
||||
TestKeyPair*
|
||||
CloneReusedKeyPair()
|
||||
{
|
||||
static PRCallOnceType initCallOnce;
|
||||
if (PR_CallOnce(&initCallOnce, InitReusedKeyPair) != PR_SUCCESS) {
|
||||
abort();
|
||||
}
|
||||
assert(reusedKeyPair);
|
||||
return reusedKeyPair->Clone();
|
||||
}
|
||||
|
||||
ByteString
|
||||
SHA1(const ByteString& toHash)
|
||||
{
|
||||
if (InitNSSIfNeeded() != Success) {
|
||||
return ByteString();
|
||||
}
|
||||
InitNSSIfNeeded();
|
||||
|
||||
uint8_t digestBuf[SHA1_LENGTH];
|
||||
SECStatus srv = PK11_HashBuf(SEC_OID_SHA1, digestBuf, toHash.data(),
|
||||
|
@ -223,10 +258,7 @@ SHA1(const ByteString& toHash)
|
|||
Result
|
||||
TestCheckPublicKey(Input subjectPublicKeyInfo)
|
||||
{
|
||||
Result rv = InitNSSIfNeeded();
|
||||
if (rv != Success) {
|
||||
return rv;
|
||||
}
|
||||
InitNSSIfNeeded();
|
||||
return CheckPublicKey(subjectPublicKeyInfo);
|
||||
}
|
||||
|
||||
|
@ -234,20 +266,14 @@ Result
|
|||
TestVerifySignedData(const SignedDataWithSignature& signedData,
|
||||
Input subjectPublicKeyInfo)
|
||||
{
|
||||
Result rv = InitNSSIfNeeded();
|
||||
if (rv != Success) {
|
||||
return rv;
|
||||
}
|
||||
InitNSSIfNeeded();
|
||||
return VerifySignedData(signedData, subjectPublicKeyInfo, nullptr);
|
||||
}
|
||||
|
||||
Result
|
||||
TestDigestBuf(Input item, /*out*/ uint8_t* digestBuf, size_t digestBufLen)
|
||||
{
|
||||
Result rv = InitNSSIfNeeded();
|
||||
if (rv != Success) {
|
||||
return rv;
|
||||
}
|
||||
InitNSSIfNeeded();
|
||||
return DigestBuf(item, digestBuf, digestBufLen);
|
||||
}
|
||||
|
||||
|
|
|
@ -143,7 +143,7 @@ OCSPResponseContext::OCSPResponseContext(const CertID& certID, time_t time)
|
|||
, certStatus(good)
|
||||
, revocationTime(0)
|
||||
, thisUpdate(time)
|
||||
, nextUpdate(time + 10)
|
||||
, nextUpdate(time + Time::ONE_DAY_IN_SECONDS)
|
||||
, includeNextUpdate(true)
|
||||
{
|
||||
}
|
||||
|
@ -349,16 +349,13 @@ YMDHMS(int16_t year, int16_t month, int16_t day,
|
|||
|
||||
static ByteString
|
||||
SignedData(const ByteString& tbsData,
|
||||
/*optional*/ TestKeyPair* keyPair,
|
||||
const TestKeyPair& keyPair,
|
||||
const ByteString& signatureAlgorithm,
|
||||
bool corrupt, /*optional*/ const ByteString* certs)
|
||||
{
|
||||
ByteString signature;
|
||||
if (keyPair) {
|
||||
if (keyPair->SignData(tbsData, signatureAlgorithm, signature)
|
||||
!= Success) {
|
||||
return ByteString();
|
||||
}
|
||||
if (keyPair.SignData(tbsData, signatureAlgorithm, signature) != Success) {
|
||||
return ByteString();
|
||||
}
|
||||
|
||||
// TODO: add ability to have signatures of bit length not divisible by 8,
|
||||
|
@ -464,31 +461,21 @@ CreateEncodedCertificate(long version, const ByteString& signature,
|
|||
const ByteString& issuerNameDER,
|
||||
time_t notBefore, time_t notAfter,
|
||||
const ByteString& subjectNameDER,
|
||||
const TestKeyPair& subjectKeyPair,
|
||||
/*optional*/ const ByteString* extensions,
|
||||
/*optional*/ TestKeyPair* issuerKeyPair,
|
||||
const ByteString& signatureAlgorithm,
|
||||
/*out*/ ScopedTestKeyPair& keyPairResult)
|
||||
const TestKeyPair& issuerKeyPair,
|
||||
const ByteString& signatureAlgorithm)
|
||||
{
|
||||
// It may be the case that privateKeyResult references the same TestKeyPair
|
||||
// as issuerKeyPair. Thus, we can't set keyPairResult until after we're done
|
||||
// with issuerKeyPair.
|
||||
ScopedTestKeyPair subjectKeyPair(GenerateKeyPair());
|
||||
if (!subjectKeyPair) {
|
||||
return ByteString();
|
||||
}
|
||||
|
||||
ByteString tbsCertificate(TBSCertificate(version, serialNumber,
|
||||
signature, issuerNameDER, notBefore,
|
||||
notAfter, subjectNameDER,
|
||||
subjectKeyPair->subjectPublicKeyInfo,
|
||||
subjectKeyPair.subjectPublicKeyInfo,
|
||||
extensions));
|
||||
if (ENCODING_FAILED(tbsCertificate)) {
|
||||
return ByteString();
|
||||
}
|
||||
|
||||
ByteString result(SignedData(tbsCertificate,
|
||||
issuerKeyPair ? issuerKeyPair
|
||||
: subjectKeyPair.get(),
|
||||
ByteString result(SignedData(tbsCertificate, issuerKeyPair,
|
||||
signatureAlgorithm, false, nullptr));
|
||||
if (ENCODING_FAILED(result)) {
|
||||
return ByteString();
|
||||
|
@ -496,8 +483,6 @@ CreateEncodedCertificate(long version, const ByteString& signature,
|
|||
|
||||
MaybeLogOutput(result, "cert");
|
||||
|
||||
keyPairResult = subjectKeyPair.release();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -763,10 +748,9 @@ BasicOCSPResponse(OCSPResponseContext& context)
|
|||
return ByteString();
|
||||
}
|
||||
|
||||
// TODO(bug 980538): certs
|
||||
return SignedData(tbsResponseData, context.signerKeyPair.get(),
|
||||
context.signatureAlgorithm,
|
||||
context.badSignature, context.certs);
|
||||
return SignedData(tbsResponseData, *context.signerKeyPair,
|
||||
context.signatureAlgorithm, context.badSignature,
|
||||
context.certs);
|
||||
}
|
||||
|
||||
// Extension ::= SEQUENCE {
|
||||
|
|
|
@ -134,6 +134,7 @@ protected:
|
|||
void operator=(const TestKeyPair&) /*= delete*/;
|
||||
};
|
||||
|
||||
TestKeyPair* CloneReusedKeyPair();
|
||||
TestKeyPair* GenerateKeyPair();
|
||||
inline void DeleteTestKeyPair(TestKeyPair* keyPair) { delete keyPair; }
|
||||
typedef ScopedPtr<TestKeyPair, DeleteTestKeyPair> ScopedTestKeyPair;
|
||||
|
@ -172,19 +173,15 @@ enum Version { v1 = 0, v2 = 1, v3 = 2 };
|
|||
// extensions must point to an array of ByteStrings, terminated with an empty
|
||||
// ByteString. (If the first item of the array is empty then an empty
|
||||
// Extensions sequence will be encoded.)
|
||||
//
|
||||
// If issuerPrivateKey is null, then the certificate will be self-signed.
|
||||
// Parameter order is based on the order of the attributes of the certificate
|
||||
// in RFC 5280.
|
||||
ByteString CreateEncodedCertificate(long version, const ByteString& signature,
|
||||
const ByteString& serialNumber,
|
||||
const ByteString& issuerNameDER,
|
||||
time_t notBefore, time_t notAfter,
|
||||
const ByteString& subjectNameDER,
|
||||
const TestKeyPair& subjectKeyPair,
|
||||
/*optional*/ const ByteString* extensions,
|
||||
/*optional*/ TestKeyPair* issuerKeyPair,
|
||||
const ByteString& signatureAlgorithm,
|
||||
/*out*/ ScopedTestKeyPair& keyPairResult);
|
||||
const TestKeyPair& issuerKeyPair,
|
||||
const ByteString& signatureAlgorithm);
|
||||
|
||||
ByteString CreateEncodedSerialNumber(long value);
|
||||
|
||||
|
|
|
@ -62,6 +62,10 @@ TEST_HARNESS_BINS += metrotestharness$(BIN_SUFFIX)
|
|||
endif
|
||||
endif
|
||||
|
||||
ifdef MOZ_DMD
|
||||
TEST_HARNESS_BINS += dmd.py
|
||||
endif
|
||||
|
||||
# Components / typelibs that don't get packaged with
|
||||
# the build, but that we need for the test harness.
|
||||
TEST_HARNESS_COMPONENTS := \
|
||||
|
|
|
@ -606,6 +606,25 @@ class XPCShellTestThread(Thread):
|
|||
|
||||
completeCmd = cmdH + cmdT + args
|
||||
|
||||
if self.test_object.get('dmd') == 'true':
|
||||
if sys.platform.startswith('linux'):
|
||||
preloadEnvVar = 'LD_PRELOAD'
|
||||
libdmd = os.path.join(self.xrePath, 'libdmd.so')
|
||||
elif sys.platform == 'osx' or sys.platform == 'darwin':
|
||||
preloadEnvVar = 'DYLD_INSERT_LIBRARIES'
|
||||
# self.xrePath is <prefix>/Contents/Resources.
|
||||
# We need <prefix>/Contents/MacOS/libdmd.dylib.
|
||||
contents_dir = os.path.dirname(self.xrePath)
|
||||
libdmd = os.path.join(contents_dir, 'MacOS', 'libdmd.dylib')
|
||||
elif sys.platform == 'win32':
|
||||
preloadEnvVar = 'MOZ_REPLACE_MALLOC_LIB'
|
||||
libdmd = os.path.join(self.xrePath, 'dmd.dll')
|
||||
|
||||
self.env['DMD'] = '--mode=test'
|
||||
self.env['PYTHON'] = sys.executable
|
||||
self.env['BREAKPAD_SYMBOLS_PATH'] = self.symbolsPath
|
||||
self.env[preloadEnvVar] = libdmd
|
||||
|
||||
testTimeoutInterval = HARNESS_TIMEOUT
|
||||
# Allow a test to request a multiple of the timeout if it is expected to take long
|
||||
if 'requesttimeoutfactor' in self.test_object:
|
||||
|
|
|
@ -258,7 +258,7 @@ let MemoryActor = protocol.ActorClass({
|
|||
allocations: []
|
||||
};
|
||||
|
||||
for (let stack of allocations) {
|
||||
for (let { frame: stack } of allocations) {
|
||||
if (stack && Cu.isDeadWrapper(stack)) {
|
||||
continue;
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче