8f73edeaf6
This adds copy constructors / assignment operator, reset(), value(), and has_value() to SkTOptional. Change-Id: I564552a75a4c612685cdaa8e80e4359b394b64a4 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/414338 Commit-Queue: Ethan Nicholas <ethannicholas@google.com> Reviewed-by: John Stiles <johnstiles@google.com>
186 lines
5.6 KiB
C++
186 lines
5.6 KiB
C++
/*
|
|
* Copyright 2021 Google LLC.
|
|
*
|
|
* Use of this source code is governed by a BSD-style license that can be
|
|
* found in the LICENSE file.
|
|
*/
|
|
|
|
#include "include/private/SkTArray.h"
|
|
#include "include/private/SkTOptional.h"
|
|
|
|
#include "tests/Test.h"
|
|
|
|
DEF_TEST(SkTOptionalEmpty, r) {
|
|
skstd::optional<int> o;
|
|
REPORTER_ASSERT(r, !o);
|
|
REPORTER_ASSERT(r, !o.has_value());
|
|
}
|
|
|
|
DEF_TEST(SkTOptionalValue, r) {
|
|
skstd::optional<const char*> o("test");
|
|
REPORTER_ASSERT(r, o);
|
|
REPORTER_ASSERT(r, o.has_value());
|
|
REPORTER_ASSERT(r, !strcmp(*o, "test"));
|
|
REPORTER_ASSERT(r, !strcmp(o.value(), "test"));
|
|
o.reset();
|
|
REPORTER_ASSERT(r, !o);
|
|
REPORTER_ASSERT(r, !o.has_value());
|
|
}
|
|
|
|
class SkTOptionalTestPayload {
|
|
public:
|
|
enum State {
|
|
kConstructed,
|
|
kCopyConstructed,
|
|
kCopyAssigned,
|
|
kMoveConstructed,
|
|
kMoveAssigned,
|
|
kMovedFrom
|
|
};
|
|
|
|
SkTOptionalTestPayload(int payload)
|
|
: fState(kConstructed)
|
|
, fPayload(payload) {}
|
|
|
|
SkTOptionalTestPayload(const SkTOptionalTestPayload& other)
|
|
: fState(kCopyConstructed)
|
|
, fPayload(other.fPayload) {}
|
|
|
|
SkTOptionalTestPayload(SkTOptionalTestPayload&& other)
|
|
: fState(kMoveConstructed)
|
|
, fPayload(other.fPayload) {
|
|
other.fState = kMovedFrom;
|
|
}
|
|
|
|
SkTOptionalTestPayload& operator=(const SkTOptionalTestPayload& other) {
|
|
fState = kCopyAssigned;
|
|
fPayload = other.fPayload;
|
|
return *this;
|
|
}
|
|
|
|
SkTOptionalTestPayload& operator=(SkTOptionalTestPayload&& other) {
|
|
fState = kMoveAssigned;
|
|
fPayload = other.fPayload;
|
|
other.fState = kMovedFrom;
|
|
return *this;
|
|
}
|
|
State fState;
|
|
int fPayload;
|
|
};
|
|
|
|
DEF_TEST(SkTOptionalConstruction, r) {
|
|
skstd::optional<SkTOptionalTestPayload> o(1);
|
|
REPORTER_ASSERT(r, o);
|
|
REPORTER_ASSERT(r, o->fState == SkTOptionalTestPayload::kConstructed);
|
|
REPORTER_ASSERT(r, o->fPayload == 1);
|
|
|
|
skstd::optional<SkTOptionalTestPayload> copy(o);
|
|
REPORTER_ASSERT(r, copy);
|
|
REPORTER_ASSERT(r, copy->fState == SkTOptionalTestPayload::kCopyConstructed);
|
|
REPORTER_ASSERT(r, copy->fPayload == 1);
|
|
REPORTER_ASSERT(r, o->fState == SkTOptionalTestPayload::kConstructed);
|
|
|
|
skstd::optional<SkTOptionalTestPayload> move(std::move(o));
|
|
REPORTER_ASSERT(r, move);
|
|
REPORTER_ASSERT(r, move->fState == SkTOptionalTestPayload::kMoveConstructed);
|
|
REPORTER_ASSERT(r, move->fPayload == 1);
|
|
// NOLINTNEXTLINE(bugprone-use-after-move)
|
|
REPORTER_ASSERT(r, o->fState == SkTOptionalTestPayload::kMovedFrom);
|
|
}
|
|
|
|
DEF_TEST(SkTOptionalMoveAssignment, r) {
|
|
skstd::optional<SkTOptionalTestPayload> o;
|
|
REPORTER_ASSERT(r, !o);
|
|
|
|
// assign to an empty optional from an empty optional
|
|
o = skstd::optional<SkTOptionalTestPayload>();
|
|
REPORTER_ASSERT(r, !o);
|
|
|
|
// assign to an empty optional from a full optional
|
|
skstd::optional<SkTOptionalTestPayload> full(1);
|
|
o = std::move(full);
|
|
REPORTER_ASSERT(r, o);
|
|
REPORTER_ASSERT(r, o->fState == SkTOptionalTestPayload::kMoveConstructed);
|
|
REPORTER_ASSERT(r, o->fPayload == 1);
|
|
// NOLINTNEXTLINE(bugprone-use-after-move)
|
|
REPORTER_ASSERT(r, full->fState == SkTOptionalTestPayload::kMovedFrom);
|
|
|
|
// assign to a full optional from a full optional
|
|
full = skstd::optional<SkTOptionalTestPayload>(2);
|
|
o = std::move(full);
|
|
REPORTER_ASSERT(r, o);
|
|
REPORTER_ASSERT(r, o->fState == SkTOptionalTestPayload::kMoveAssigned);
|
|
REPORTER_ASSERT(r, o->fPayload == 2);
|
|
// NOLINTNEXTLINE(bugprone-use-after-move)
|
|
REPORTER_ASSERT(r, full->fState == SkTOptionalTestPayload::kMovedFrom);
|
|
|
|
// assign to a full optional from an empty optional
|
|
o = skstd::optional<SkTOptionalTestPayload>();
|
|
REPORTER_ASSERT(r, !o);
|
|
}
|
|
|
|
DEF_TEST(SkTOptionalCopyAssignment, r) {
|
|
skstd::optional<SkTOptionalTestPayload> o;
|
|
REPORTER_ASSERT(r, !o);
|
|
|
|
skstd::optional<SkTOptionalTestPayload> empty;
|
|
skstd::optional<SkTOptionalTestPayload> full(1);
|
|
|
|
// assign to an empty optional from an empty optional
|
|
o = empty;
|
|
REPORTER_ASSERT(r, !o);
|
|
|
|
// assign to an empty optional from a full optional
|
|
o = full;
|
|
REPORTER_ASSERT(r, o);
|
|
REPORTER_ASSERT(r, o->fState == SkTOptionalTestPayload::kCopyConstructed);
|
|
REPORTER_ASSERT(r, o->fPayload == 1);
|
|
|
|
// assign to a full optional from a full optional
|
|
o = full;
|
|
REPORTER_ASSERT(r, o);
|
|
REPORTER_ASSERT(r, o->fState == SkTOptionalTestPayload::kCopyAssigned);
|
|
REPORTER_ASSERT(r, o->fPayload == 1);
|
|
|
|
// assign to a full optional from an empty optional
|
|
o = empty;
|
|
REPORTER_ASSERT(r, !o);
|
|
}
|
|
|
|
DEF_TEST(SkTOptionalNoDefaultConstructor, r) {
|
|
class NoDefaultConstructor {
|
|
public:
|
|
NoDefaultConstructor(int value)
|
|
: fValue(value) {}
|
|
|
|
int fValue;
|
|
};
|
|
|
|
skstd::optional<NoDefaultConstructor> o1;
|
|
REPORTER_ASSERT(r, !o1);
|
|
skstd::optional<NoDefaultConstructor> o2(5);
|
|
REPORTER_ASSERT(r, o2);
|
|
REPORTER_ASSERT(r, o2->fValue == 5);
|
|
o1 = std::move(o2);
|
|
REPORTER_ASSERT(r, o1);
|
|
REPORTER_ASSERT(r, o1->fValue == 5);
|
|
}
|
|
|
|
DEF_TEST(SkTOptionalSelfAssignment, r) {
|
|
skstd::optional<SkString> empty;
|
|
skstd::optional<SkString>& emptyRef = empty;
|
|
empty = emptyRef;
|
|
REPORTER_ASSERT(r, !empty);
|
|
empty = std::move(emptyRef);
|
|
REPORTER_ASSERT(r, !empty);
|
|
|
|
skstd::optional<SkString> full("full");
|
|
skstd::optional<SkString>& fullRef = full;
|
|
full = fullRef;
|
|
REPORTER_ASSERT(r, full);
|
|
REPORTER_ASSERT(r, *full == SkString("full"));
|
|
full = std::move(fullRef);
|
|
REPORTER_ASSERT(r, full);
|
|
REPORTER_ASSERT(r, *full == SkString("full"));
|
|
}
|