1779c4247SMichael J. Spencer //===- unittests/ErrorOrTest.cpp - ErrorOr.h tests ------------------------===//
2779c4247SMichael J. Spencer //
3*2946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*2946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
5*2946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6779c4247SMichael J. Spencer //
7779c4247SMichael J. Spencer //===----------------------------------------------------------------------===//
8779c4247SMichael J. Spencer 
9779c4247SMichael J. Spencer #include "llvm/Support/ErrorOr.h"
102a826e40SRafael Espindola #include "llvm/Support/Errc.h"
11779c4247SMichael J. Spencer #include "gtest/gtest.h"
12779c4247SMichael J. Spencer #include <memory>
13779c4247SMichael J. Spencer 
14779c4247SMichael J. Spencer using namespace llvm;
15779c4247SMichael J. Spencer 
16779c4247SMichael J. Spencer namespace {
17779c4247SMichael J. Spencer 
t1()18779c4247SMichael J. Spencer ErrorOr<int> t1() { return 1; }
t2()192a826e40SRafael Espindola ErrorOr<int> t2() { return errc::invalid_argument; }
20779c4247SMichael J. Spencer 
TEST(ErrorOr,SimpleValue)21779c4247SMichael J. Spencer TEST(ErrorOr, SimpleValue) {
22779c4247SMichael J. Spencer   ErrorOr<int> a = t1();
2398d3c101SRafael Espindola   // FIXME: This is probably a bug in gtest. EXPECT_TRUE should expand to
2498d3c101SRafael Espindola   // include the !! to make it friendly to explicit bool operators.
2598d3c101SRafael Espindola   EXPECT_TRUE(!!a);
26779c4247SMichael J. Spencer   EXPECT_EQ(1, *a);
27779c4247SMichael J. Spencer 
28cd56deb6SRafael Espindola   ErrorOr<int> b = a;
29cd56deb6SRafael Espindola   EXPECT_EQ(1, *b);
30cd56deb6SRafael Espindola 
31779c4247SMichael J. Spencer   a = t2();
32779c4247SMichael J. Spencer   EXPECT_FALSE(a);
332a826e40SRafael Espindola   EXPECT_EQ(a.getError(), errc::invalid_argument);
3408e028e1SNAKAMURA Takumi #ifdef EXPECT_DEBUG_DEATH
35779c4247SMichael J. Spencer   EXPECT_DEBUG_DEATH(*a, "Cannot get value when an error exists");
3608e028e1SNAKAMURA Takumi #endif
37779c4247SMichael J. Spencer }
38779c4247SMichael J. Spencer 
t3()39779c4247SMichael J. Spencer ErrorOr<std::unique_ptr<int> > t3() {
40779c4247SMichael J. Spencer   return std::unique_ptr<int>(new int(3));
41779c4247SMichael J. Spencer }
42779c4247SMichael J. Spencer 
TEST(ErrorOr,Types)43779c4247SMichael J. Spencer TEST(ErrorOr, Types) {
44779c4247SMichael J. Spencer   int x;
45779c4247SMichael J. Spencer   ErrorOr<int&> a(x);
46779c4247SMichael J. Spencer   *a = 42;
47779c4247SMichael J. Spencer   EXPECT_EQ(42, x);
48779c4247SMichael J. Spencer 
49779c4247SMichael J. Spencer   // Move only types.
50779c4247SMichael J. Spencer   EXPECT_EQ(3, **t3());
51779c4247SMichael J. Spencer }
5218131ae0SMichael J. Spencer 
5318131ae0SMichael J. Spencer struct B {};
5418131ae0SMichael J. Spencer struct D : B {};
5518131ae0SMichael J. Spencer 
TEST(ErrorOr,Covariant)5618131ae0SMichael J. Spencer TEST(ErrorOr, Covariant) {
5766f09ad0SCraig Topper   ErrorOr<B*> b(ErrorOr<D*>(nullptr));
5866f09ad0SCraig Topper   b = ErrorOr<D*>(nullptr);
5918131ae0SMichael J. Spencer 
6066f09ad0SCraig Topper   ErrorOr<std::unique_ptr<B> > b1(ErrorOr<std::unique_ptr<D> >(nullptr));
6166f09ad0SCraig Topper   b1 = ErrorOr<std::unique_ptr<D> >(nullptr);
6299b96f42SDavid Blaikie 
6399b96f42SDavid Blaikie   ErrorOr<std::unique_ptr<int>> b2(ErrorOr<int *>(nullptr));
6499b96f42SDavid Blaikie   ErrorOr<int *> b3(nullptr);
6599b96f42SDavid Blaikie   ErrorOr<std::unique_ptr<int>> b4(b3);
6618131ae0SMichael J. Spencer }
6799b96f42SDavid Blaikie 
TEST(ErrorOr,Comparison)68abc39841SMichael J. Spencer TEST(ErrorOr, Comparison) {
6974f29324SRafael Espindola   ErrorOr<int> x(errc::no_such_file_or_directory);
7074f29324SRafael Espindola   EXPECT_EQ(x, errc::no_such_file_or_directory);
71e5fa25a0SNick Lewycky }
72e5fa25a0SNick Lewycky 
TEST(ErrorOr,ImplicitConversion)73e5fa25a0SNick Lewycky TEST(ErrorOr, ImplicitConversion) {
74e5fa25a0SNick Lewycky   ErrorOr<std::string> x("string literal");
75e5fa25a0SNick Lewycky   EXPECT_TRUE(!!x);
76e5fa25a0SNick Lewycky }
77e5fa25a0SNick Lewycky 
TEST(ErrorOr,ImplicitConversionCausesMove)78e5fa25a0SNick Lewycky TEST(ErrorOr, ImplicitConversionCausesMove) {
79e5fa25a0SNick Lewycky   struct Source {};
80e5fa25a0SNick Lewycky   struct Destination {
81e5fa25a0SNick Lewycky     Destination(const Source&) {}
82e5fa25a0SNick Lewycky     Destination(Source&&) = delete;
83e5fa25a0SNick Lewycky   };
84e5fa25a0SNick Lewycky   Source s;
85e5fa25a0SNick Lewycky   ErrorOr<Destination> x = s;
86e5fa25a0SNick Lewycky   EXPECT_TRUE(!!x);
87e5fa25a0SNick Lewycky }
88e5fa25a0SNick Lewycky 
TEST(ErrorOr,ImplicitConversionNoAmbiguity)89e5fa25a0SNick Lewycky TEST(ErrorOr, ImplicitConversionNoAmbiguity) {
90e5fa25a0SNick Lewycky   struct CastsToErrorCode {
91e5fa25a0SNick Lewycky     CastsToErrorCode() = default;
92e5fa25a0SNick Lewycky     CastsToErrorCode(std::error_code) {}
93e5fa25a0SNick Lewycky     operator std::error_code() { return errc::invalid_argument; }
94e5fa25a0SNick Lewycky   } casts_to_error_code;
95e5fa25a0SNick Lewycky   ErrorOr<CastsToErrorCode> x1(casts_to_error_code);
96e5fa25a0SNick Lewycky   ErrorOr<CastsToErrorCode> x2 = casts_to_error_code;
97e5fa25a0SNick Lewycky   ErrorOr<CastsToErrorCode> x3 = {casts_to_error_code};
98e5fa25a0SNick Lewycky   ErrorOr<CastsToErrorCode> x4{casts_to_error_code};
99e5fa25a0SNick Lewycky   ErrorOr<CastsToErrorCode> x5(errc::no_such_file_or_directory);
100e5fa25a0SNick Lewycky   ErrorOr<CastsToErrorCode> x6 = errc::no_such_file_or_directory;
101e5fa25a0SNick Lewycky   ErrorOr<CastsToErrorCode> x7 = {errc::no_such_file_or_directory};
102e5fa25a0SNick Lewycky   ErrorOr<CastsToErrorCode> x8{errc::no_such_file_or_directory};
103e5fa25a0SNick Lewycky   EXPECT_TRUE(!!x1);
104e5fa25a0SNick Lewycky   EXPECT_TRUE(!!x2);
105e5fa25a0SNick Lewycky   EXPECT_TRUE(!!x3);
106e5fa25a0SNick Lewycky   EXPECT_TRUE(!!x4);
107e5fa25a0SNick Lewycky   EXPECT_FALSE(x5);
108e5fa25a0SNick Lewycky   EXPECT_FALSE(x6);
109e5fa25a0SNick Lewycky   EXPECT_FALSE(x7);
110e5fa25a0SNick Lewycky   EXPECT_FALSE(x8);
111abc39841SMichael J. Spencer }
112abc39841SMichael J. Spencer 
11399b96f42SDavid Blaikie // ErrorOr<int*> x(nullptr);
11499b96f42SDavid Blaikie // ErrorOr<std::unique_ptr<int>> y = x; // invalid conversion
11599b96f42SDavid Blaikie static_assert(
11699b96f42SDavid Blaikie     !std::is_convertible<const ErrorOr<int *> &,
11799b96f42SDavid Blaikie                          ErrorOr<std::unique_ptr<int>>>::value,
11899b96f42SDavid Blaikie     "do not invoke explicit ctors in implicit conversion from lvalue");
11999b96f42SDavid Blaikie 
12099b96f42SDavid Blaikie // ErrorOr<std::unique_ptr<int>> y = ErrorOr<int*>(nullptr); // invalid
12199b96f42SDavid Blaikie //                                                           // conversion
12299b96f42SDavid Blaikie static_assert(
12399b96f42SDavid Blaikie     !std::is_convertible<ErrorOr<int *> &&,
12499b96f42SDavid Blaikie                          ErrorOr<std::unique_ptr<int>>>::value,
12599b96f42SDavid Blaikie     "do not invoke explicit ctors in implicit conversion from rvalue");
12699b96f42SDavid Blaikie 
12799b96f42SDavid Blaikie // ErrorOr<int*> x(nullptr);
12899b96f42SDavid Blaikie // ErrorOr<std::unique_ptr<int>> y;
12999b96f42SDavid Blaikie // y = x; // invalid conversion
13060707939SRichard Smith static_assert(!std::is_assignable<ErrorOr<std::unique_ptr<int>>&,
13199b96f42SDavid Blaikie                                   const ErrorOr<int *> &>::value,
13299b96f42SDavid Blaikie               "do not invoke explicit ctors in assignment");
13399b96f42SDavid Blaikie 
13499b96f42SDavid Blaikie // ErrorOr<std::unique_ptr<int>> x;
13599b96f42SDavid Blaikie // x = ErrorOr<int*>(nullptr); // invalid conversion
13660707939SRichard Smith static_assert(!std::is_assignable<ErrorOr<std::unique_ptr<int>>&,
13799b96f42SDavid Blaikie                                   ErrorOr<int *> &&>::value,
13899b96f42SDavid Blaikie               "do not invoke explicit ctors in assignment");
139779c4247SMichael J. Spencer } // end anon namespace
140