/* * 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 o; REPORTER_ASSERT(r, !o); REPORTER_ASSERT(r, !o.has_value()); } DEF_TEST(SkTOptionalValue, r) { skstd::optional 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 o(1); REPORTER_ASSERT(r, o); REPORTER_ASSERT(r, o->fState == SkTOptionalTestPayload::kConstructed); REPORTER_ASSERT(r, o->fPayload == 1); skstd::optional 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 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 o; REPORTER_ASSERT(r, !o); // assign to an empty optional from an empty optional o = skstd::optional(); REPORTER_ASSERT(r, !o); // assign to an empty optional from a full optional skstd::optional 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(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(); REPORTER_ASSERT(r, !o); } DEF_TEST(SkTOptionalCopyAssignment, r) { skstd::optional o; REPORTER_ASSERT(r, !o); skstd::optional empty; skstd::optional 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 o1; REPORTER_ASSERT(r, !o1); skstd::optional 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 empty; skstd::optional& emptyRef = empty; empty = emptyRef; REPORTER_ASSERT(r, !empty); empty = std::move(emptyRef); REPORTER_ASSERT(r, !empty); skstd::optional full("full"); skstd::optional& 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")); }