mirror of
https://github.com/roytam1/palemoon27.git
synced 2026-05-26 05:37:11 +00:00
a7bc0406ee
- Bug 1155006: Fix unified build sensitivities in js/src/jit. r=shu (6e24e1af1) - Bug 1162766 - Fix more bad implicit constructors in js. r=evilpie (39961b06d) - Bug 1151606 - Stream atoms instead of raw pointers for native functions in tracked optimizations. (r=djvj) (7641ee9d6) - pointer style (540728104) - Bug 1154997 - Deal with self-hosted builtins when stringifying tracked optimization type info. (r=djvj) (92f9a54e6) - pointer style (45742d820) - Bug 1154115 - Rewrite the JSAPI profiling API to use a FrameHandle, as to avoid multiple lookups in JitcodeGlobalTable. (r=djvj) (4d202ba9e) - Bug 1119023 - Timeline in new perf tool should filter out markers, r=jsantell (6fc1a8bbe) - Bug 1132755 - Allocations tree has a bunch of columns that don't make sense, r=jsantell (1ae9ee7e2) - Bug 1142744 - Fix tests broken by bug 1132755, r=me (cc495f72d) - Bug 1133058 - OptionsView button, when clicked, should have an 'open' attribute. r=vp (65a78d896) - Bug 1132765 - Pass through performance memory options for 'probability' and 'maxLogLength' from the front to the memory actor. r=vp (f9bbbe098) - Bug 1141817 - Fix yield statement to correctly return memory actor state so that the performance tool can poll for allocations during recording. r=vp (2ddf7d528) - Bug 1141817 - Followup to fix additional intermittents like bug 1132370, r=vp (eab962f01) - Bug 1142748 - Use a single configuration for starting/stopping recordings, r=jsantell (0181b319a) - bit of Bug 879008 - New UI for the sampling Profiler (32c4d0fe8) - Bug 1123815 - Merge gum into fx-team to enable the Performance++ tool, r=me (84aabbd61) - Bug 1143933 - Expose raw JIT optimization information in performance front end. r=vp,shu (f68a6df50) - Bug 1143915 - Allow multiple calls to memory and timeline actor's start methods, to return the local start time from the actor. r=vp (028ac4187) - Bug 978948 - Add animation generator support for setTimeout in the canvas debugger. r=vp (42d623452) - Bug 985488 - Allow canvas debugger to time out and stop recording frames. Canvas debugger 'wait' style now matches other media styles. Update labels in canvas debugger to explicitly state that it's waiting for rAF cycles, rather than appearing as if something went wrong. r=vporof (b4670d843) - Bug 1144163 - Add a rulers highlighter; added unit test. r=pbrosset (5811a67d0) - Bug 1144163 - Add a rulers highlighter; added highlighter. r=pbrosset (779f88bdd) - Bug 1144163 - Add a rulers highlighter; added gcli command and button. r=pbrosset (d0d13da51) - Bug 1110550 - Enable performance overview graphs to rerender and change on devtools theme switch. r=vp (bd91ca7cf) - Bug 1149630 - Performance graphs should inherit from a common graph and be similarly styled. r=vporof (481c841f1) - Bug 1150733 - Correctly internationalize jit samples label. r=vporof, r=flod (b5612d1a6) - Bug 1137518 - FlameGraph's destroy function should be async, r=jsantell (f103e4c15) - Bug 1137503 - Avoid potential infinite loops in `findOptimalTickInterval` functions, r=jsantell (95df6c04a) - Bug 1121194 - Support vertical panning for the flamegraph in the new performance tool, r=jsantell (06241b5b2) - Bug 1121180 - Support dark theme in flamecharts for the performance tool. r=vp (c76abe237) - Bug 1059308 - Add Target.isTabActor to tell if the remote tab actor supports attach/detach requests. r=jryans (e03dcef93) - Bug 1132370 - Wrong State: Expected 'attached', but current state is 'detached', r=jsantell (e884e8db9) - No Bug - Fix documentation for _startMemory and _stopMemory in performance/modules/front.js, r=me DONTBUILD (d79090b31) - Bug 1147656 - Remove duplicate profiler defaults from the front end and just use on the server. r=vp (35c015dd0) - Bug 1046234 - Add more DevTools Telemetry measures (display size etc) r=pbrosset, r=gijs (a235681b4) - actually package telemetry.js (e8f3a58a4) - Bug 1077464 - Wire console.profile/profileEnd to the new performance tool. Move most of the recording-model logic from the front end into the PerformanceFront and PerformanceActorConnection so it can manage recordings without the front end being viewed. r=vp,jryans,pbrosset (eef8e18c3) - Bug 1144363 - Fix this._telemetry is undefined in gDevTools. r=bgrins (ba7d02902) - init telemetry, missing parts of Bug 866642 (1e70df975) - do not use sysctl.h on Linux anymore, since it is not provided by recent glibc (b2467d7ce) - clean up some telemetry issues of histogram, parts of Bug 974171 (d30c8d0ad) - move devtools to browser - part 1 (9a856f452) - Bug 1291423: Explicitly qualify the destructor call that we invoke in Maybe::reset. r=Waldo (944904a7d) - Bug 1148075 - Dynamically add XUL commands for the debugger frontend. r=vporof (60bc91f8f) - Bug 1147945 - Let the profiler's buffer size and sample rate be configurable via prefs. r=vp (acebcbdd9) - Bug 1124326 - Improve packageDir support for Cordova. r=ochameau (4b736580a) - Bug 1124326 - Support Cordova w/o build file. r=ochameau (d4b50aeae) - Bug 1134029 - Fix 'Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsIURI.host]' timeouts, r=jsantell (18d16a5d0) - Bug 1147806 - Content frame filtering is confused when profiling FxOS, r=jsantell (b3c62c552) - Bug 1108843 - Generalize platform data in call tree view when platform data is hidden. r=vporof (354553ed7) - Bug 1138928 - Display only function name and file, instead of full url, in flame graphs. r=vp (4169689c1) - Bug 1152605 - Should not show host names for chrome URIs. r=vporof (c6dcf9e78) - Bug 1147604 - Inverted call trees should list (root) as leaves. r=jsantell (01768267f) - Bug 1075450 - Disable some Awesomebar actions for private windows r=mak (21d5586e7) - Bug 1120616 - Part 1: Implement filter styles in rule view r=bgrins (b66ee0282) - Bug 1120616 - Part 2: Add unit tests for filter styles in rule view r=bgrins (2892503d8) - Bug 1120616 - Part 3: Adjust the styles in the computed view's filter style search r=bgrins (41f8fae1b) - Bug 1120616 - Part 4: Add textbox context menu for rule and computed view r=bgrins (ff3f868ad) - Bug 1120616 - Part 5: Refactor style inspector tests to use synthesizeKeys r=bgrins (41db021d7) - Bug 1102219 - Part 5: Replace more `String.prototype.contains` with `String.prototype.includes` in chrome code. r=till (86ed03588) - Bug 1154018 - Check to see that nsIURI's host exists when parsing location for framenodes, and cache failures. r=vp (9494d52e7) - Bug 1160691 - Optimize FrameUtils.isContent and FrameUtils.parseLocation. (r=jsantell) (09118fd5d) - Bug 1154115 - Make the performance devtool handle the new profiler JSON format. (r=jsantell,vporof) (e3e5be7a4) - Bug 1059308 - Make frame selection button to work in browser toolbox. r=jryans,past (30fe6e61e) - Bug 1059308 - Fix tests to support chrome actor. r=jryans (01cf3926c) - Bug 1147042 - Rename attachProcess to getProcess. r=ochameau (0393ffb80) - Bug 1145824 - Profiler actor and performance tools now handle passing in a startTime to filter out SPS profiles on platform rather than client. r=vp,fitzgen (f225116ba) - Bug 1157718 - Do not use Array.prototype.includes in production code that leaves nightly in performance tool. r=fitzgen (ff06d284e) - Bug 1140728 - Rename 'Memory' to 'Allocations' in the new performance tool. r=jsantell (f584e720f) - Bug 1137500 - Always wait for the overview to be rendered in tests after a recording finishes, unless otherwise specified, r=jsantell (59825e179) - Bug 1137487 - AbstractCanvasGraph's destroy function should be async, r=jsantell (a17ae00b5) - Bug 1132758 - Performance feature visibility now based on a per recording-basis, dependent on features enabled and server support. r=vp (0d080a7c2) - Bug 1147035 - Make DeveloperToolbar.jsm use the gBrowser.contentDocumentAsCPOW shortcut. r=past. (251eff125) - Bug 1151168 - Don't flush profiled threads that are pending deletion on JS shutdown and don't delete expired markers when resetting the profile buffer. (r=djvj) (90721313a)
845 lines
28 KiB
C++
845 lines
28 KiB
C++
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
/* 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/. */
|
|
|
|
#include <utility>
|
|
|
|
#include "mozilla/Assertions.h"
|
|
#include "mozilla/Attributes.h"
|
|
#include "mozilla/Compiler.h"
|
|
#include "mozilla/Maybe.h"
|
|
#include "mozilla/Move.h"
|
|
#include "mozilla/Types.h"
|
|
#include "mozilla/TypeTraits.h"
|
|
#include "mozilla/UniquePtr.h"
|
|
|
|
using mozilla::IsSame;
|
|
using mozilla::Maybe;
|
|
using mozilla::Move;
|
|
using mozilla::Nothing;
|
|
using mozilla::Some;
|
|
using mozilla::Swap;
|
|
using mozilla::ToMaybe;
|
|
using mozilla::UniquePtr;
|
|
|
|
#if MOZ_IS_MSVC
|
|
template<typename T> struct Identity { typedef T type; };
|
|
# define DECLTYPE(EXPR) Identity<decltype(EXPR)>::type
|
|
#else
|
|
# define DECLTYPE(EXPR) decltype(EXPR)
|
|
#endif
|
|
|
|
#define RUN_TEST(t) \
|
|
do { \
|
|
bool cond = (t()); \
|
|
if (!cond) \
|
|
return 1; \
|
|
cond = AllDestructorsWereCalled(); \
|
|
MOZ_ASSERT(cond, "Failed to destroy all objects during test: " #t); \
|
|
if (!cond) \
|
|
return 1; \
|
|
} while (false)
|
|
|
|
enum Status
|
|
{
|
|
eWasDefaultConstructed,
|
|
eWasConstructed,
|
|
eWasCopyConstructed,
|
|
eWasMoveConstructed,
|
|
eWasCopyAssigned,
|
|
eWasMoveAssigned,
|
|
eWasMovedFrom
|
|
};
|
|
|
|
static size_t sUndestroyedObjects = 0;
|
|
|
|
static bool AllDestructorsWereCalled()
|
|
{
|
|
return sUndestroyedObjects == 0;
|
|
}
|
|
|
|
struct BasicValue
|
|
{
|
|
BasicValue()
|
|
: mStatus(eWasDefaultConstructed)
|
|
, mTag(0)
|
|
{
|
|
++sUndestroyedObjects;
|
|
}
|
|
|
|
explicit BasicValue(int aTag)
|
|
: mStatus(eWasConstructed)
|
|
, mTag(aTag)
|
|
{
|
|
++sUndestroyedObjects;
|
|
}
|
|
|
|
BasicValue(const BasicValue& aOther)
|
|
: mStatus(eWasCopyConstructed)
|
|
, mTag(aOther.mTag)
|
|
{
|
|
++sUndestroyedObjects;
|
|
}
|
|
|
|
BasicValue(BasicValue&& aOther)
|
|
: mStatus(eWasMoveConstructed)
|
|
, mTag(aOther.mTag)
|
|
{
|
|
++sUndestroyedObjects;
|
|
aOther.mStatus = eWasMovedFrom;
|
|
aOther.mTag = 0;
|
|
}
|
|
|
|
~BasicValue() { --sUndestroyedObjects; }
|
|
|
|
BasicValue& operator=(const BasicValue& aOther)
|
|
{
|
|
mStatus = eWasCopyAssigned;
|
|
mTag = aOther.mTag;
|
|
return *this;
|
|
}
|
|
|
|
BasicValue& operator=(BasicValue&& aOther)
|
|
{
|
|
mStatus = eWasMoveAssigned;
|
|
mTag = aOther.mTag;
|
|
aOther.mStatus = eWasMovedFrom;
|
|
aOther.mTag = 0;
|
|
return *this;
|
|
}
|
|
|
|
bool operator==(const BasicValue& aOther) const
|
|
{
|
|
return mTag == aOther.mTag;
|
|
}
|
|
|
|
bool operator<(const BasicValue& aOther) const
|
|
{
|
|
return mTag < aOther.mTag;
|
|
}
|
|
|
|
Status GetStatus() const { return mStatus; }
|
|
void SetTag(int aValue) { mTag = aValue; }
|
|
int GetTag() const { return mTag; }
|
|
|
|
private:
|
|
Status mStatus;
|
|
int mTag;
|
|
};
|
|
|
|
struct UncopyableValue
|
|
{
|
|
UncopyableValue()
|
|
: mStatus(eWasDefaultConstructed)
|
|
{
|
|
++sUndestroyedObjects;
|
|
}
|
|
|
|
UncopyableValue(UncopyableValue&& aOther)
|
|
: mStatus(eWasMoveConstructed)
|
|
{
|
|
++sUndestroyedObjects;
|
|
aOther.mStatus = eWasMovedFrom;
|
|
}
|
|
|
|
~UncopyableValue() { --sUndestroyedObjects; }
|
|
|
|
UncopyableValue& operator=(UncopyableValue&& aOther)
|
|
{
|
|
mStatus = eWasMoveAssigned;
|
|
aOther.mStatus = eWasMovedFrom;
|
|
return *this;
|
|
}
|
|
|
|
Status GetStatus() { return mStatus; }
|
|
|
|
private:
|
|
UncopyableValue(const UncopyableValue& aOther) = delete;
|
|
UncopyableValue& operator=(const UncopyableValue& aOther) = delete;
|
|
|
|
Status mStatus;
|
|
};
|
|
|
|
struct UnmovableValue
|
|
{
|
|
UnmovableValue()
|
|
: mStatus(eWasDefaultConstructed)
|
|
{
|
|
++sUndestroyedObjects;
|
|
}
|
|
|
|
UnmovableValue(const UnmovableValue& aOther)
|
|
: mStatus(eWasCopyConstructed)
|
|
{
|
|
++sUndestroyedObjects;
|
|
}
|
|
|
|
~UnmovableValue() { --sUndestroyedObjects; }
|
|
|
|
UnmovableValue& operator=(const UnmovableValue& aOther)
|
|
{
|
|
mStatus = eWasCopyAssigned;
|
|
return *this;
|
|
}
|
|
|
|
Status GetStatus() { return mStatus; }
|
|
|
|
private:
|
|
UnmovableValue(UnmovableValue&& aOther) = delete;
|
|
UnmovableValue& operator=(UnmovableValue&& aOther) = delete;
|
|
|
|
Status mStatus;
|
|
};
|
|
|
|
struct UncopyableUnmovableValue
|
|
{
|
|
UncopyableUnmovableValue()
|
|
: mStatus(eWasDefaultConstructed)
|
|
{
|
|
++sUndestroyedObjects;
|
|
}
|
|
|
|
explicit UncopyableUnmovableValue(int)
|
|
: mStatus(eWasConstructed)
|
|
{
|
|
++sUndestroyedObjects;
|
|
}
|
|
|
|
~UncopyableUnmovableValue() { --sUndestroyedObjects; }
|
|
|
|
Status GetStatus() { return mStatus; }
|
|
|
|
private:
|
|
UncopyableUnmovableValue(const UncopyableUnmovableValue& aOther) = delete;
|
|
UncopyableUnmovableValue& operator=(const UncopyableUnmovableValue& aOther) = delete;
|
|
UncopyableUnmovableValue(UncopyableUnmovableValue&& aOther) = delete;
|
|
UncopyableUnmovableValue& operator=(UncopyableUnmovableValue&& aOther) = delete;
|
|
|
|
Status mStatus;
|
|
};
|
|
|
|
static bool
|
|
TestBasicFeatures()
|
|
{
|
|
// Check that a Maybe<T> is initialized to Nothing.
|
|
Maybe<BasicValue> mayValue;
|
|
static_assert(IsSame<BasicValue, DECLTYPE(mayValue)::ValueType>::value,
|
|
"Should have BasicValue ValueType");
|
|
MOZ_RELEASE_ASSERT(!mayValue);
|
|
MOZ_RELEASE_ASSERT(!mayValue.isSome());
|
|
MOZ_RELEASE_ASSERT(mayValue.isNothing());
|
|
|
|
// Check that emplace() default constructs and the accessors work.
|
|
mayValue.emplace();
|
|
MOZ_RELEASE_ASSERT(mayValue);
|
|
MOZ_RELEASE_ASSERT(mayValue.isSome());
|
|
MOZ_RELEASE_ASSERT(!mayValue.isNothing());
|
|
MOZ_RELEASE_ASSERT(*mayValue == BasicValue());
|
|
MOZ_RELEASE_ASSERT(mayValue.value() == BasicValue());
|
|
static_assert(IsSame<BasicValue, DECLTYPE(mayValue.value())>::value,
|
|
"value() should return a BasicValue");
|
|
MOZ_RELEASE_ASSERT(mayValue.ref() == BasicValue());
|
|
static_assert(IsSame<BasicValue&, DECLTYPE(mayValue.ref())>::value,
|
|
"ref() should return a BasicValue&");
|
|
MOZ_RELEASE_ASSERT(mayValue.ptr() != nullptr);
|
|
static_assert(IsSame<BasicValue*, DECLTYPE(mayValue.ptr())>::value,
|
|
"ptr() should return a BasicValue*");
|
|
MOZ_RELEASE_ASSERT(mayValue->GetStatus() == eWasDefaultConstructed);
|
|
|
|
// Check that reset() works.
|
|
mayValue.reset();
|
|
MOZ_RELEASE_ASSERT(!mayValue);
|
|
MOZ_RELEASE_ASSERT(!mayValue.isSome());
|
|
MOZ_RELEASE_ASSERT(mayValue.isNothing());
|
|
|
|
// Check that emplace(T1) calls the correct constructor.
|
|
mayValue.emplace(1);
|
|
MOZ_RELEASE_ASSERT(mayValue);
|
|
MOZ_RELEASE_ASSERT(mayValue->GetStatus() == eWasConstructed);
|
|
MOZ_RELEASE_ASSERT(mayValue->GetTag() == 1);
|
|
mayValue.reset();
|
|
MOZ_RELEASE_ASSERT(!mayValue);
|
|
|
|
// Check that Some() and Nothing() work.
|
|
mayValue = Some(BasicValue(2));
|
|
MOZ_RELEASE_ASSERT(mayValue);
|
|
MOZ_RELEASE_ASSERT(mayValue->GetStatus() == eWasMoveConstructed);
|
|
MOZ_RELEASE_ASSERT(mayValue->GetTag() == 2);
|
|
mayValue = Nothing();
|
|
MOZ_RELEASE_ASSERT(!mayValue);
|
|
|
|
// Check that the accessors work through a const ref.
|
|
mayValue.emplace();
|
|
const Maybe<BasicValue>& mayValueCRef = mayValue;
|
|
MOZ_RELEASE_ASSERT(mayValueCRef);
|
|
MOZ_RELEASE_ASSERT(mayValueCRef.isSome());
|
|
MOZ_RELEASE_ASSERT(!mayValueCRef.isNothing());
|
|
MOZ_RELEASE_ASSERT(*mayValueCRef == BasicValue());
|
|
MOZ_RELEASE_ASSERT(mayValueCRef.value() == BasicValue());
|
|
static_assert(IsSame<BasicValue, DECLTYPE(mayValueCRef.value())>::value,
|
|
"value() should return a BasicValue");
|
|
MOZ_RELEASE_ASSERT(mayValueCRef.ref() == BasicValue());
|
|
static_assert(IsSame<const BasicValue&,
|
|
DECLTYPE(mayValueCRef.ref())>::value,
|
|
"ref() should return a const BasicValue&");
|
|
MOZ_RELEASE_ASSERT(mayValueCRef.ptr() != nullptr);
|
|
static_assert(IsSame<const BasicValue*,
|
|
DECLTYPE(mayValueCRef.ptr())>::value,
|
|
"ptr() should return a const BasicValue*");
|
|
MOZ_RELEASE_ASSERT(mayValueCRef->GetStatus() == eWasDefaultConstructed);
|
|
mayValue.reset();
|
|
|
|
return true;
|
|
}
|
|
|
|
static bool
|
|
TestCopyAndMove()
|
|
{
|
|
// Check that we get moves when possible for types that can support both moves
|
|
// and copies.
|
|
Maybe<BasicValue> mayBasicValue = Some(BasicValue(1));
|
|
MOZ_RELEASE_ASSERT(mayBasicValue->GetStatus() == eWasMoveConstructed);
|
|
MOZ_RELEASE_ASSERT(mayBasicValue->GetTag() == 1);
|
|
mayBasicValue = Some(BasicValue(2));
|
|
MOZ_RELEASE_ASSERT(mayBasicValue->GetStatus() == eWasMoveAssigned);
|
|
MOZ_RELEASE_ASSERT(mayBasicValue->GetTag() == 2);
|
|
mayBasicValue.reset();
|
|
mayBasicValue.emplace(BasicValue(3));
|
|
MOZ_RELEASE_ASSERT(mayBasicValue->GetStatus() == eWasMoveConstructed);
|
|
MOZ_RELEASE_ASSERT(mayBasicValue->GetTag() == 3);
|
|
|
|
// Check that we get copies when moves aren't possible.
|
|
Maybe<BasicValue> mayBasicValue2 = Some(*mayBasicValue);
|
|
MOZ_RELEASE_ASSERT(mayBasicValue2->GetStatus() == eWasCopyConstructed);
|
|
MOZ_RELEASE_ASSERT(mayBasicValue2->GetTag() == 3);
|
|
mayBasicValue->SetTag(4);
|
|
mayBasicValue2 = mayBasicValue;
|
|
// This test should work again when we fix bug 1052940.
|
|
//MOZ_RELEASE_ASSERT(mayBasicValue2->GetStatus() == eWasCopyAssigned);
|
|
MOZ_RELEASE_ASSERT(mayBasicValue2->GetTag() == 4);
|
|
mayBasicValue->SetTag(5);
|
|
mayBasicValue2.reset();
|
|
mayBasicValue2.emplace(*mayBasicValue);
|
|
MOZ_RELEASE_ASSERT(mayBasicValue2->GetStatus() == eWasCopyConstructed);
|
|
MOZ_RELEASE_ASSERT(mayBasicValue2->GetTag() == 5);
|
|
|
|
// Check that Move() works. (Another sanity check for move support.)
|
|
Maybe<BasicValue> mayBasicValue3 = Some(Move(*mayBasicValue));
|
|
MOZ_RELEASE_ASSERT(mayBasicValue3->GetStatus() == eWasMoveConstructed);
|
|
MOZ_RELEASE_ASSERT(mayBasicValue3->GetTag() == 5);
|
|
MOZ_RELEASE_ASSERT(mayBasicValue->GetStatus() == eWasMovedFrom);
|
|
mayBasicValue2->SetTag(6);
|
|
mayBasicValue3 = Some(Move(*mayBasicValue2));
|
|
MOZ_RELEASE_ASSERT(mayBasicValue3->GetStatus() == eWasMoveAssigned);
|
|
MOZ_RELEASE_ASSERT(mayBasicValue3->GetTag() == 6);
|
|
MOZ_RELEASE_ASSERT(mayBasicValue2->GetStatus() == eWasMovedFrom);
|
|
Maybe<BasicValue> mayBasicValue4;
|
|
mayBasicValue4.emplace(Move(*mayBasicValue3));
|
|
MOZ_RELEASE_ASSERT(mayBasicValue4->GetStatus() == eWasMoveConstructed);
|
|
MOZ_RELEASE_ASSERT(mayBasicValue4->GetTag() == 6);
|
|
MOZ_RELEASE_ASSERT(mayBasicValue3->GetStatus() == eWasMovedFrom);
|
|
|
|
// Check that we always get copies for types that don't support moves.
|
|
// XXX(seth): These tests fail but probably shouldn't. For now we'll just
|
|
// consider using Maybe with types that allow copies but have deleted or
|
|
// private move constructors, or which do not support copy assignment, to
|
|
// be supported only to the extent that we need for existing code to work.
|
|
// These tests should work again when we fix bug 1052940.
|
|
/*
|
|
Maybe<UnmovableValue> mayUnmovableValue = Some(UnmovableValue());
|
|
MOZ_RELEASE_ASSERT(mayUnmovableValue->GetStatus() == eWasCopyConstructed);
|
|
mayUnmovableValue = Some(UnmovableValue());
|
|
MOZ_RELEASE_ASSERT(mayUnmovableValue->GetStatus() == eWasCopyAssigned);
|
|
mayUnmovableValue.reset();
|
|
mayUnmovableValue.emplace(UnmovableValue());
|
|
MOZ_RELEASE_ASSERT(mayUnmovableValue->GetStatus() == eWasCopyConstructed);
|
|
*/
|
|
|
|
// Check that types that only support moves, but not copies, work.
|
|
Maybe<UncopyableValue> mayUncopyableValue = Some(UncopyableValue());
|
|
MOZ_RELEASE_ASSERT(mayUncopyableValue->GetStatus() == eWasMoveConstructed);
|
|
mayUncopyableValue = Some(UncopyableValue());
|
|
MOZ_RELEASE_ASSERT(mayUncopyableValue->GetStatus() == eWasMoveAssigned);
|
|
mayUncopyableValue.reset();
|
|
mayUncopyableValue.emplace(UncopyableValue());
|
|
MOZ_RELEASE_ASSERT(mayUncopyableValue->GetStatus() == eWasMoveConstructed);
|
|
|
|
// Check that types that support neither moves or copies work.
|
|
Maybe<UncopyableUnmovableValue> mayUncopyableUnmovableValue;
|
|
mayUncopyableUnmovableValue.emplace();
|
|
MOZ_RELEASE_ASSERT(mayUncopyableUnmovableValue->GetStatus() == eWasDefaultConstructed);
|
|
mayUncopyableUnmovableValue.reset();
|
|
mayUncopyableUnmovableValue.emplace(0);
|
|
MOZ_RELEASE_ASSERT(mayUncopyableUnmovableValue->GetStatus() == eWasConstructed);
|
|
|
|
return true;
|
|
}
|
|
|
|
static BasicValue* sStaticBasicValue = nullptr;
|
|
|
|
static BasicValue
|
|
MakeBasicValue()
|
|
{
|
|
return BasicValue(9);
|
|
}
|
|
|
|
static BasicValue&
|
|
MakeBasicValueRef()
|
|
{
|
|
return *sStaticBasicValue;
|
|
}
|
|
|
|
static BasicValue*
|
|
MakeBasicValuePtr()
|
|
{
|
|
return sStaticBasicValue;
|
|
}
|
|
|
|
static bool
|
|
TestFunctionalAccessors()
|
|
{
|
|
BasicValue value(9);
|
|
sStaticBasicValue = new BasicValue(9);
|
|
|
|
// Check that the 'some' case of functional accessors works.
|
|
Maybe<BasicValue> someValue = Some(BasicValue(3));
|
|
MOZ_RELEASE_ASSERT(someValue.valueOr(value) == BasicValue(3));
|
|
static_assert(IsSame<BasicValue,
|
|
DECLTYPE(someValue.valueOr(value))>::value,
|
|
"valueOr should return a BasicValue");
|
|
MOZ_RELEASE_ASSERT(someValue.valueOrFrom(&MakeBasicValue) == BasicValue(3));
|
|
static_assert(IsSame<BasicValue,
|
|
DECLTYPE(someValue.valueOrFrom(&MakeBasicValue))>::value,
|
|
"valueOrFrom should return a BasicValue");
|
|
MOZ_RELEASE_ASSERT(someValue.ptrOr(&value) != &value);
|
|
static_assert(IsSame<BasicValue*,
|
|
DECLTYPE(someValue.ptrOr(&value))>::value,
|
|
"ptrOr should return a BasicValue*");
|
|
MOZ_RELEASE_ASSERT(*someValue.ptrOrFrom(&MakeBasicValuePtr) == BasicValue(3));
|
|
static_assert(IsSame<BasicValue*,
|
|
DECLTYPE(someValue.ptrOrFrom(&MakeBasicValuePtr))>::value,
|
|
"ptrOrFrom should return a BasicValue*");
|
|
MOZ_RELEASE_ASSERT(someValue.refOr(value) == BasicValue(3));
|
|
static_assert(IsSame<BasicValue&,
|
|
DECLTYPE(someValue.refOr(value))>::value,
|
|
"refOr should return a BasicValue&");
|
|
MOZ_RELEASE_ASSERT(someValue.refOrFrom(&MakeBasicValueRef) == BasicValue(3));
|
|
static_assert(IsSame<BasicValue&,
|
|
DECLTYPE(someValue.refOrFrom(&MakeBasicValueRef))>::value,
|
|
"refOrFrom should return a BasicValue&");
|
|
|
|
// Check that the 'some' case works through a const reference.
|
|
const Maybe<BasicValue>& someValueCRef = someValue;
|
|
MOZ_RELEASE_ASSERT(someValueCRef.valueOr(value) == BasicValue(3));
|
|
static_assert(IsSame<BasicValue,
|
|
DECLTYPE(someValueCRef.valueOr(value))>::value,
|
|
"valueOr should return a BasicValue");
|
|
MOZ_RELEASE_ASSERT(someValueCRef.valueOrFrom(&MakeBasicValue) == BasicValue(3));
|
|
static_assert(IsSame<BasicValue,
|
|
DECLTYPE(someValueCRef.valueOrFrom(&MakeBasicValue))>::value,
|
|
"valueOrFrom should return a BasicValue");
|
|
MOZ_RELEASE_ASSERT(someValueCRef.ptrOr(&value) != &value);
|
|
static_assert(IsSame<const BasicValue*,
|
|
DECLTYPE(someValueCRef.ptrOr(&value))>::value,
|
|
"ptrOr should return a const BasicValue*");
|
|
MOZ_RELEASE_ASSERT(*someValueCRef.ptrOrFrom(&MakeBasicValuePtr) == BasicValue(3));
|
|
static_assert(IsSame<const BasicValue*,
|
|
DECLTYPE(someValueCRef.ptrOrFrom(&MakeBasicValuePtr))>::value,
|
|
"ptrOrFrom should return a const BasicValue*");
|
|
MOZ_RELEASE_ASSERT(someValueCRef.refOr(value) == BasicValue(3));
|
|
static_assert(IsSame<const BasicValue&,
|
|
DECLTYPE(someValueCRef.refOr(value))>::value,
|
|
"refOr should return a const BasicValue&");
|
|
MOZ_RELEASE_ASSERT(someValueCRef.refOrFrom(&MakeBasicValueRef) == BasicValue(3));
|
|
static_assert(IsSame<const BasicValue&,
|
|
DECLTYPE(someValueCRef.refOrFrom(&MakeBasicValueRef))>::value,
|
|
"refOrFrom should return a const BasicValue&");
|
|
|
|
// Check that the 'none' case of functional accessors works.
|
|
Maybe<BasicValue> noneValue;
|
|
MOZ_RELEASE_ASSERT(noneValue.valueOr(value) == BasicValue(9));
|
|
static_assert(IsSame<BasicValue,
|
|
DECLTYPE(noneValue.valueOr(value))>::value,
|
|
"valueOr should return a BasicValue");
|
|
MOZ_RELEASE_ASSERT(noneValue.valueOrFrom(&MakeBasicValue) == BasicValue(9));
|
|
static_assert(IsSame<BasicValue,
|
|
DECLTYPE(noneValue.valueOrFrom(&MakeBasicValue))>::value,
|
|
"valueOrFrom should return a BasicValue");
|
|
MOZ_RELEASE_ASSERT(noneValue.ptrOr(&value) == &value);
|
|
static_assert(IsSame<BasicValue*,
|
|
DECLTYPE(noneValue.ptrOr(&value))>::value,
|
|
"ptrOr should return a BasicValue*");
|
|
MOZ_RELEASE_ASSERT(*noneValue.ptrOrFrom(&MakeBasicValuePtr) == BasicValue(9));
|
|
static_assert(IsSame<BasicValue*,
|
|
DECLTYPE(noneValue.ptrOrFrom(&MakeBasicValuePtr))>::value,
|
|
"ptrOrFrom should return a BasicValue*");
|
|
MOZ_RELEASE_ASSERT(noneValue.refOr(value) == BasicValue(9));
|
|
static_assert(IsSame<BasicValue&,
|
|
DECLTYPE(noneValue.refOr(value))>::value,
|
|
"refOr should return a BasicValue&");
|
|
MOZ_RELEASE_ASSERT(noneValue.refOrFrom(&MakeBasicValueRef) == BasicValue(9));
|
|
static_assert(IsSame<BasicValue&,
|
|
DECLTYPE(noneValue.refOrFrom(&MakeBasicValueRef))>::value,
|
|
"refOrFrom should return a BasicValue&");
|
|
|
|
// Check that the 'none' case works through a const reference.
|
|
const Maybe<BasicValue>& noneValueCRef = noneValue;
|
|
MOZ_RELEASE_ASSERT(noneValueCRef.valueOr(value) == BasicValue(9));
|
|
static_assert(IsSame<BasicValue,
|
|
DECLTYPE(noneValueCRef.valueOr(value))>::value,
|
|
"valueOr should return a BasicValue");
|
|
MOZ_RELEASE_ASSERT(noneValueCRef.valueOrFrom(&MakeBasicValue) == BasicValue(9));
|
|
static_assert(IsSame<BasicValue,
|
|
DECLTYPE(noneValueCRef.valueOrFrom(&MakeBasicValue))>::value,
|
|
"valueOrFrom should return a BasicValue");
|
|
MOZ_RELEASE_ASSERT(noneValueCRef.ptrOr(&value) == &value);
|
|
static_assert(IsSame<const BasicValue*,
|
|
DECLTYPE(noneValueCRef.ptrOr(&value))>::value,
|
|
"ptrOr should return a const BasicValue*");
|
|
MOZ_RELEASE_ASSERT(*noneValueCRef.ptrOrFrom(&MakeBasicValuePtr) == BasicValue(9));
|
|
static_assert(IsSame<const BasicValue*,
|
|
DECLTYPE(noneValueCRef.ptrOrFrom(&MakeBasicValuePtr))>::value,
|
|
"ptrOrFrom should return a const BasicValue*");
|
|
MOZ_RELEASE_ASSERT(noneValueCRef.refOr(value) == BasicValue(9));
|
|
static_assert(IsSame<const BasicValue&,
|
|
DECLTYPE(noneValueCRef.refOr(value))>::value,
|
|
"refOr should return a const BasicValue&");
|
|
MOZ_RELEASE_ASSERT(noneValueCRef.refOrFrom(&MakeBasicValueRef) == BasicValue(9));
|
|
static_assert(IsSame<const BasicValue&,
|
|
DECLTYPE(noneValueCRef.refOrFrom(&MakeBasicValueRef))>::value,
|
|
"refOrFrom should return a const BasicValue&");
|
|
|
|
// Clean up so the undestroyed objects count stays accurate.
|
|
delete sStaticBasicValue;
|
|
sStaticBasicValue = nullptr;
|
|
|
|
return true;
|
|
}
|
|
|
|
static bool gFunctionWasApplied = false;
|
|
|
|
static void
|
|
IncrementTag(BasicValue& aValue)
|
|
{
|
|
gFunctionWasApplied = true;
|
|
aValue.SetTag(aValue.GetTag() + 1);
|
|
}
|
|
|
|
static void
|
|
IncrementTagBy(BasicValue& aValue, int aAmount)
|
|
{
|
|
gFunctionWasApplied = true;
|
|
aValue.SetTag(aValue.GetTag() + aAmount);
|
|
}
|
|
|
|
static void
|
|
AccessValue(const BasicValue&)
|
|
{
|
|
gFunctionWasApplied = true;
|
|
}
|
|
|
|
static void
|
|
AccessValueWithArg(const BasicValue&, int)
|
|
{
|
|
gFunctionWasApplied = true;
|
|
}
|
|
|
|
struct IncrementTagFunctor
|
|
{
|
|
IncrementTagFunctor() : mBy(1), mArgMoved(false) { }
|
|
|
|
void operator()(BasicValue& aValue)
|
|
{
|
|
aValue.SetTag(aValue.GetTag() + mBy.GetTag());
|
|
}
|
|
|
|
void operator()(BasicValue& aValue, const BasicValue& aArg)
|
|
{
|
|
mArgMoved = false;
|
|
aValue.SetTag(aValue.GetTag() + aArg.GetTag());
|
|
}
|
|
|
|
void operator()(BasicValue& aValue, BasicValue&& aArg)
|
|
{
|
|
mArgMoved = true;
|
|
aValue.SetTag(aValue.GetTag() + aArg.GetTag());
|
|
}
|
|
|
|
BasicValue mBy;
|
|
bool mArgMoved;
|
|
};
|
|
|
|
static bool
|
|
TestApply()
|
|
{
|
|
// Check that apply handles the 'Nothing' case.
|
|
gFunctionWasApplied = false;
|
|
Maybe<BasicValue> mayValue;
|
|
mayValue.apply(&IncrementTag);
|
|
mayValue.apply(&AccessValue);
|
|
mayValue.apply(&IncrementTagBy, 1);
|
|
mayValue.apply(&AccessValueWithArg, 1);
|
|
MOZ_RELEASE_ASSERT(!gFunctionWasApplied);
|
|
|
|
// Check that apply handles the 'Some' case.
|
|
mayValue = Some(BasicValue(1));
|
|
mayValue.apply(&IncrementTag);
|
|
MOZ_RELEASE_ASSERT(gFunctionWasApplied);
|
|
MOZ_RELEASE_ASSERT(mayValue->GetTag() == 2);
|
|
gFunctionWasApplied = false;
|
|
mayValue.apply(&AccessValue);
|
|
MOZ_RELEASE_ASSERT(gFunctionWasApplied);
|
|
gFunctionWasApplied = false;
|
|
mayValue.apply(&IncrementTagBy, 2);
|
|
MOZ_RELEASE_ASSERT(gFunctionWasApplied);
|
|
MOZ_RELEASE_ASSERT(mayValue->GetTag() == 4);
|
|
gFunctionWasApplied = false;
|
|
mayValue.apply(&AccessValueWithArg, 1);
|
|
MOZ_RELEASE_ASSERT(gFunctionWasApplied);
|
|
|
|
// Check that apply works with a const reference.
|
|
const Maybe<BasicValue>& mayValueCRef = mayValue;
|
|
gFunctionWasApplied = false;
|
|
mayValueCRef.apply(&AccessValue);
|
|
MOZ_RELEASE_ASSERT(gFunctionWasApplied);
|
|
gFunctionWasApplied = false;
|
|
mayValueCRef.apply(&AccessValueWithArg, 1);
|
|
MOZ_RELEASE_ASSERT(gFunctionWasApplied);
|
|
|
|
// Check that apply works with functors.
|
|
IncrementTagFunctor tagIncrementer;
|
|
MOZ_RELEASE_ASSERT(tagIncrementer.mBy.GetStatus() == eWasConstructed);
|
|
mayValue = Some(BasicValue(1));
|
|
mayValue.apply(tagIncrementer);
|
|
MOZ_RELEASE_ASSERT(mayValue->GetTag() == 2);
|
|
MOZ_RELEASE_ASSERT(tagIncrementer.mBy.GetStatus() == eWasConstructed);
|
|
mayValue.apply(tagIncrementer, BasicValue(2));
|
|
MOZ_RELEASE_ASSERT(mayValue->GetTag() == 4);
|
|
MOZ_RELEASE_ASSERT(tagIncrementer.mBy.GetStatus() == eWasConstructed);
|
|
MOZ_RELEASE_ASSERT(tagIncrementer.mArgMoved == true);
|
|
BasicValue incrementBy(3);
|
|
mayValue.apply(tagIncrementer, incrementBy);
|
|
MOZ_RELEASE_ASSERT(mayValue->GetTag() == 7);
|
|
MOZ_RELEASE_ASSERT(tagIncrementer.mBy.GetStatus() == eWasConstructed);
|
|
MOZ_RELEASE_ASSERT(tagIncrementer.mArgMoved == false);
|
|
|
|
return true;
|
|
}
|
|
|
|
static int
|
|
TimesTwo(const BasicValue& aValue)
|
|
{
|
|
return aValue.GetTag() * 2;
|
|
}
|
|
|
|
static int
|
|
TimesTwoAndResetOriginal(BasicValue& aValue)
|
|
{
|
|
int tag = aValue.GetTag();
|
|
aValue.SetTag(1);
|
|
return tag * 2;
|
|
}
|
|
|
|
static int
|
|
TimesNum(const BasicValue& aValue, int aNum)
|
|
{
|
|
return aValue.GetTag() * aNum;
|
|
}
|
|
|
|
static int
|
|
TimesNumAndResetOriginal(BasicValue& aValue, int aNum)
|
|
{
|
|
int tag = aValue.GetTag();
|
|
aValue.SetTag(1);
|
|
return tag * aNum;
|
|
}
|
|
|
|
struct MultiplyTagFunctor
|
|
{
|
|
MultiplyTagFunctor() : mBy(2), mArgMoved(false) { }
|
|
|
|
int operator()(BasicValue& aValue)
|
|
{
|
|
return aValue.GetTag() * mBy.GetTag();
|
|
}
|
|
|
|
int operator()(BasicValue& aValue, const BasicValue& aArg)
|
|
{
|
|
mArgMoved = false;
|
|
return aValue.GetTag() * aArg.GetTag();
|
|
}
|
|
|
|
int operator()(BasicValue& aValue, BasicValue&& aArg)
|
|
{
|
|
mArgMoved = true;
|
|
return aValue.GetTag() * aArg.GetTag();
|
|
}
|
|
|
|
BasicValue mBy;
|
|
bool mArgMoved;
|
|
};
|
|
|
|
static bool
|
|
TestMap()
|
|
{
|
|
// Check that map handles the 'Nothing' case.
|
|
Maybe<BasicValue> mayValue;
|
|
MOZ_RELEASE_ASSERT(mayValue.map(&TimesTwo) == Nothing());
|
|
static_assert(IsSame<Maybe<int>,
|
|
DECLTYPE(mayValue.map(&TimesTwo))>::value,
|
|
"map(TimesTwo) should return a Maybe<int>");
|
|
MOZ_RELEASE_ASSERT(mayValue.map(&TimesTwoAndResetOriginal) == Nothing());
|
|
MOZ_RELEASE_ASSERT(mayValue.map(&TimesNum, 3) == Nothing());
|
|
static_assert(IsSame<Maybe<int>,
|
|
DECLTYPE(mayValue.map(&TimesNum, 3))>::value,
|
|
"map(TimesNum, 3) should return a Maybe<int>");
|
|
MOZ_RELEASE_ASSERT(mayValue.map(&TimesNumAndResetOriginal, 3) == Nothing());
|
|
|
|
// Check that map handles the 'Some' case.
|
|
mayValue = Some(BasicValue(2));
|
|
MOZ_RELEASE_ASSERT(mayValue.map(&TimesTwo) == Some(4));
|
|
MOZ_RELEASE_ASSERT(mayValue.map(&TimesTwoAndResetOriginal) == Some(4));
|
|
MOZ_RELEASE_ASSERT(mayValue->GetTag() == 1);
|
|
mayValue = Some(BasicValue(2));
|
|
MOZ_RELEASE_ASSERT(mayValue.map(&TimesNum, 3) == Some(6));
|
|
MOZ_RELEASE_ASSERT(mayValue.map(&TimesNumAndResetOriginal, 3) == Some(6));
|
|
MOZ_RELEASE_ASSERT(mayValue->GetTag() == 1);
|
|
|
|
// Check that map works with a const reference.
|
|
mayValue->SetTag(2);
|
|
const Maybe<BasicValue>& mayValueCRef = mayValue;
|
|
MOZ_RELEASE_ASSERT(mayValueCRef.map(&TimesTwo) == Some(4));
|
|
static_assert(IsSame<Maybe<int>,
|
|
DECLTYPE(mayValueCRef.map(&TimesTwo))>::value,
|
|
"map(TimesTwo) should return a Maybe<int>");
|
|
MOZ_RELEASE_ASSERT(mayValueCRef.map(&TimesNum, 3) == Some(6));
|
|
static_assert(IsSame<Maybe<int>,
|
|
DECLTYPE(mayValueCRef.map(&TimesNum, 3))>::value,
|
|
"map(TimesNum, 3) should return a Maybe<int>");
|
|
|
|
// Check that map works with functors.
|
|
// XXX(seth): Support for functors will be added in bug 1054115; it had to be
|
|
// ripped out temporarily because of incompatibilities with GCC 4.4.
|
|
/*
|
|
MultiplyTagFunctor tagMultiplier;
|
|
MOZ_RELEASE_ASSERT(tagMultiplier.mBy.GetStatus() == eWasConstructed);
|
|
MOZ_RELEASE_ASSERT(mayValue.map(tagMultiplier) == Some(4));
|
|
MOZ_RELEASE_ASSERT(tagMultiplier.mBy.GetStatus() == eWasConstructed);
|
|
MOZ_RELEASE_ASSERT(mayValue.map(tagMultiplier, BasicValue(3)) == Some(6));
|
|
MOZ_RELEASE_ASSERT(tagMultiplier.mBy.GetStatus() == eWasConstructed);
|
|
MOZ_RELEASE_ASSERT(tagMultiplier.mArgMoved == true);
|
|
BasicValue multiplyBy(3);
|
|
MOZ_RELEASE_ASSERT(mayValue.map(tagMultiplier, multiplyBy) == Some(6));
|
|
MOZ_RELEASE_ASSERT(tagMultiplier.mBy.GetStatus() == eWasConstructed);
|
|
MOZ_RELEASE_ASSERT(tagMultiplier.mArgMoved == false);
|
|
*/
|
|
|
|
return true;
|
|
}
|
|
|
|
static bool
|
|
TestToMaybe()
|
|
{
|
|
BasicValue value(1);
|
|
BasicValue* nullPointer = nullptr;
|
|
|
|
// Check that a non-null pointer translates into a Some value.
|
|
Maybe<BasicValue> mayValue = ToMaybe(&value);
|
|
static_assert(IsSame<Maybe<BasicValue>, DECLTYPE(ToMaybe(&value))>::value,
|
|
"ToMaybe should return a Maybe<BasicValue>");
|
|
MOZ_RELEASE_ASSERT(mayValue.isSome());
|
|
MOZ_RELEASE_ASSERT(mayValue->GetTag() == 1);
|
|
MOZ_RELEASE_ASSERT(mayValue->GetStatus() == eWasCopyConstructed);
|
|
MOZ_RELEASE_ASSERT(value.GetStatus() != eWasMovedFrom);
|
|
|
|
// Check that a null pointer translates into a Nothing value.
|
|
mayValue = ToMaybe(nullPointer);
|
|
static_assert(IsSame<Maybe<BasicValue>, DECLTYPE(ToMaybe(nullPointer))>::value,
|
|
"ToMaybe should return a Maybe<BasicValue>");
|
|
MOZ_RELEASE_ASSERT(mayValue.isNothing());
|
|
|
|
return true;
|
|
}
|
|
|
|
static bool
|
|
TestComparisonOperators()
|
|
{
|
|
Maybe<BasicValue> nothingValue = Nothing();
|
|
Maybe<BasicValue> anotherNothingValue = Nothing();
|
|
Maybe<BasicValue> oneValue = Some(BasicValue(1));
|
|
Maybe<BasicValue> anotherOneValue = Some(BasicValue(1));
|
|
Maybe<BasicValue> twoValue = Some(BasicValue(2));
|
|
|
|
// Check equality.
|
|
MOZ_RELEASE_ASSERT(nothingValue == anotherNothingValue);
|
|
MOZ_RELEASE_ASSERT(oneValue == anotherOneValue);
|
|
|
|
// Check inequality.
|
|
MOZ_RELEASE_ASSERT(nothingValue != oneValue);
|
|
MOZ_RELEASE_ASSERT(oneValue != nothingValue);
|
|
MOZ_RELEASE_ASSERT(oneValue != twoValue);
|
|
|
|
// Check '<'.
|
|
MOZ_RELEASE_ASSERT(nothingValue < oneValue);
|
|
MOZ_RELEASE_ASSERT(oneValue < twoValue);
|
|
|
|
// Check '<='.
|
|
MOZ_RELEASE_ASSERT(nothingValue <= anotherNothingValue);
|
|
MOZ_RELEASE_ASSERT(nothingValue <= oneValue);
|
|
MOZ_RELEASE_ASSERT(oneValue <= oneValue);
|
|
MOZ_RELEASE_ASSERT(oneValue <= twoValue);
|
|
|
|
// Check '>'.
|
|
MOZ_RELEASE_ASSERT(oneValue > nothingValue);
|
|
MOZ_RELEASE_ASSERT(twoValue > oneValue);
|
|
|
|
// Check '>='.
|
|
MOZ_RELEASE_ASSERT(nothingValue >= anotherNothingValue);
|
|
MOZ_RELEASE_ASSERT(oneValue >= nothingValue);
|
|
MOZ_RELEASE_ASSERT(oneValue >= oneValue);
|
|
MOZ_RELEASE_ASSERT(twoValue >= oneValue);
|
|
|
|
return true;
|
|
}
|
|
|
|
// Check that Maybe<> can wrap a superclass that happens to also be a concrete
|
|
// class (i.e. that the compiler doesn't warn when we invoke the superclass's
|
|
// destructor explicitly in |reset()|.
|
|
class MySuperClass {
|
|
virtual void VirtualMethod() { /* do nothing */ }
|
|
};
|
|
|
|
class MyDerivedClass : public MySuperClass {
|
|
void VirtualMethod() override { /* do nothing */ }
|
|
};
|
|
|
|
static bool
|
|
TestVirtualFunction() {
|
|
Maybe<MySuperClass> super;
|
|
super.emplace();
|
|
super.reset();
|
|
|
|
Maybe<MyDerivedClass> derived;
|
|
derived.emplace();
|
|
derived.reset();
|
|
|
|
// If this compiles successfully, we've passed.
|
|
return true;
|
|
}
|
|
|
|
int
|
|
main()
|
|
{
|
|
RUN_TEST(TestBasicFeatures);
|
|
RUN_TEST(TestCopyAndMove);
|
|
RUN_TEST(TestFunctionalAccessors);
|
|
RUN_TEST(TestApply);
|
|
RUN_TEST(TestMap);
|
|
RUN_TEST(TestToMaybe);
|
|
RUN_TEST(TestComparisonOperators);
|
|
RUN_TEST(TestVirtualFunction);
|
|
|
|
return 0;
|
|
}
|