summaryrefslogtreecommitdiff
path: root/indra/newview/tests
diff options
context:
space:
mode:
authorBrad Payne (Vir Linden) <vir@lindenlab.com>2021-03-17 13:54:18 +0100
committerBrad Payne (Vir Linden) <vir@lindenlab.com>2021-03-17 13:54:18 +0100
commit47b3078c93a763f67103ff67f0fe8b6ac5794370 (patch)
tree5c28a887869a58c29cd59f05979a2030f63c6a34 /indra/newview/tests
parent60d62c767be3576cb674a817b90028951d6ee3b0 (diff)
SL-14999 - C++ feature tests
Diffstat (limited to 'indra/newview/tests')
-rw-r--r--indra/newview/tests/cppfeatures_test.cpp372
1 files changed, 245 insertions, 127 deletions
diff --git a/indra/newview/tests/cppfeatures_test.cpp b/indra/newview/tests/cppfeatures_test.cpp
index 15aa1cd6d6..8399bb12ff 100644
--- a/indra/newview/tests/cppfeatures_test.cpp
+++ b/indra/newview/tests/cppfeatures_test.cpp
@@ -1,127 +1,245 @@
-/**
- * @file cppfeatures_test
- * @author Vir
- * @date 2021-03
- * @brief cpp features
- *
- * $LicenseInfo:firstyear=2021&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2021, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-// Tests related to newer C++ features, for verifying support across compilers and platforms
-
-#include "linden_common.h"
-#include "../test/lltut.h"
-
-namespace tut
-{
-
-struct cpp_features_test {};
-typedef test_group<cpp_features_test> cpp_features_test_t;
-typedef cpp_features_test_t::object cpp_features_test_object_t;
-tut::cpp_features_test_t tut_cpp_features_test("LLCPPFeatures");
-
-// bracket initializers
-// Can initialize containers or values using curly brackets
-template<> template<>
-void cpp_features_test_object_t::test<1>()
-{
- S32 explicit_val{3};
- ensure(explicit_val==3);
-
- S32 default_val{};
- ensure(default_val==0);
-
- std::vector<S32> fibs{1,1,2,3,5};
- ensure(fibs[4]==5);
-}
-
-// auto
-//
-// https://en.cppreference.com/w/cpp/language/auto
-//
-// Can use auto in place of a more complex type specification, if the compiler can infer the type
-template<> template<>
-void cpp_features_test_object_t::test<2>()
-{
- std::vector<S32> numbers{3,6,9};
-
- // auto element
- auto& aval = numbers[1];
- ensure("auto element", aval==6);
-
- // auto iterator (non-const)
- auto it = numbers.rbegin();
- *it += 1;
- S32 val = *it;
- ensure("auto iterator", val==10);
-}
-
-// range for
-//
-// https://en.cppreference.com/w/cpp/language/range-for
-//
-// Can iterate over containers without explicit iterator
-template<> template<>
-void cpp_features_test_object_t::test<3>()
-{
-
- // Traditional iterator for with container
- //
- // Problems:
- // * Have to create a new variable for the iterator, which is unrelated to the problem you're trying to solve.
- // * Redundant and somewhat fragile. Have to make sure begin() and end() are both from the right container.
- std::vector<S32> numbers{3,6,9};
- for (auto it = numbers.begin(); it != numbers.end(); ++it)
- {
- auto& n = *it;
- n *= 2;
- }
- ensure("iterator for vector", numbers[2]==18);
-
- // Range for with container
- //
- // Under the hood, this is doing the same thing as the traditional
- // for loop above. Still uses begin() and end() but you don't have
- // to access them directly.
- std::vector<S32> numbersb{3,6,9};
- for (auto& n: numbersb)
- {
- n *= 2;
- }
- ensure("range for vector", numbersb[2]==18);
-
- // Range for over a C-style array.
- //
- // This is handy because the language determines the range automatically.
- // Getting this right manually is a little trickier.
- S32 pows[] = {1,2,4,8,16};
- S32 sum{};
- for (const auto& v: pows)
- {
- sum += v;
- }
- ensure("for C-array", sum==31);
-}
-
-
-
-}
+/**
+ * @file cppfeatures_test
+ * @author Vir
+ * @date 2021-03
+ * @brief cpp features
+ *
+ * $LicenseInfo:firstyear=2021&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2021, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+// Tests related to newer C++ features, for verifying support across compilers and platforms
+
+#include "linden_common.h"
+#include "../test/lltut.h"
+
+namespace tut
+{
+
+struct cpp_features_test {};
+typedef test_group<cpp_features_test> cpp_features_test_t;
+typedef cpp_features_test_t::object cpp_features_test_object_t;
+tut::cpp_features_test_t tut_cpp_features_test("LLCPPFeatures");
+
+// bracket initializers
+// Can initialize containers or values using curly brackets
+template<> template<>
+void cpp_features_test_object_t::test<1>()
+{
+ S32 explicit_val{3};
+ ensure(explicit_val==3);
+
+ S32 default_val{};
+ ensure(default_val==0);
+
+ std::vector<S32> fibs{1,1,2,3,5};
+ ensure(fibs[4]==5);
+}
+
+// auto
+//
+// https://en.cppreference.com/w/cpp/language/auto
+//
+// Can use auto in place of a more complex type specification, if the compiler can infer the type
+template<> template<>
+void cpp_features_test_object_t::test<2>()
+{
+ std::vector<S32> numbers{3,6,9};
+
+ // auto element
+ auto& aval = numbers[1];
+ ensure("auto element", aval==6);
+
+ // auto iterator (non-const)
+ auto it = numbers.rbegin();
+ *it += 1;
+ S32 val = *it;
+ ensure("auto iterator", val==10);
+}
+
+// range for
+//
+// https://en.cppreference.com/w/cpp/language/range-for
+//
+// Can iterate over containers without explicit iterator
+template<> template<>
+void cpp_features_test_object_t::test<3>()
+{
+
+ // Traditional iterator for with container
+ //
+ // Problems:
+ // * Have to create a new variable for the iterator, which is unrelated to the problem you're trying to solve.
+ // * Redundant and somewhat fragile. Have to make sure begin() and end() are both from the right container.
+ std::vector<S32> numbers{3,6,9};
+ for (auto it = numbers.begin(); it != numbers.end(); ++it)
+ {
+ auto& n = *it;
+ n *= 2;
+ }
+ ensure("iterator for vector", numbers[2]==18);
+
+ // Range for with container
+ //
+ // Under the hood, this is doing the same thing as the traditional
+ // for loop above. Still uses begin() and end() but you don't have
+ // to access them directly.
+ std::vector<S32> numbersb{3,6,9};
+ for (auto& n: numbersb)
+ {
+ n *= 2;
+ }
+ ensure("range for vector", numbersb[2]==18);
+
+ // Range for over a C-style array.
+ //
+ // This is handy because the language determines the range automatically.
+ // Getting this right manually is a little trickier.
+ S32 pows[] = {1,2,4,8,16};
+ S32 sum{};
+ for (const auto& v: pows)
+ {
+ sum += v;
+ }
+ ensure("for C-array", sum==31);
+}
+
+// override specifier
+//
+// https://en.cppreference.com/w/cpp/language/override
+//
+// Specify that a particular class function is an override of a virtual function.
+// Benefits:
+// * Makes code somewhat easier to read by showing intent.
+// * Prevents mistakes where you think something is an override but it doesn't actually match the declaration in the parent class.
+// Drawbacks:
+// * Some compilers require that any class using override must use it consistently for all functions.
+// This makes switching a class to use override a lot more work.
+
+class Foo
+{
+public:
+ virtual bool is_happy() const = 0;
+};
+
+class Bar: public Foo
+{
+public:
+ bool is_happy() const override { return true; }
+ // Override would fail: non-const declaration doesn't match parent
+ // bool is_happy() override { return true; }
+ // Override would fail: wrong name
+ // bool is_happx() override { return true; }
+};
+
+template<> template<>
+void cpp_features_test_object_t::test<4>()
+{
+ Bar b;
+ ensure("override", b.is_happy());
+}
+
+// final
+//
+// https://en.cppreference.com/w/cpp/language/final: "Specifies that a
+// virtual function cannot be overridden in a derived class or that a
+// class cannot be inherited from."
+
+class Vehicle
+{
+public:
+ virtual bool has_wheels() const = 0;
+};
+
+class WheeledVehicle: public Vehicle
+{
+public:
+ virtual bool has_wheels() const final override { return true; }
+};
+
+class Bicycle: public WheeledVehicle
+{
+public:
+ // Error: can't override final version in WheeledVehicle
+ // virtual bool has_wheels() override const { return true; }
+};
+
+template<> template<>
+void cpp_features_test_object_t::test<5>()
+{
+ Bicycle bi;
+ ensure("final", bi.has_wheels());
+}
+
+// deleted function declaration
+//
+// https://en.cppreference.com/w/cpp/language/function#Deleted_functions
+//
+// Typical case: copy constructor doesn't make sense for a particular class, so you want to make
+// sure the no one tries to copy-construct an instance of the class, and that the
+// compiler won't generate a copy constructor for you automatically.
+// Traditional fix is to declare a
+// copy constructor but never implement it, giving you a link-time error if anyone tries to use it.
+// Now you can explicitly declare a function to be deleted, which has at least two advantages over
+// the old way:
+// * Makes the intention clear
+// * Creates an error sooner, at compile time
+
+class DoNotCopy
+{
+public:
+ DoNotCopy() {}
+ DoNotCopy(const DoNotCopy& ref) = delete;
+};
+
+template<> template<>
+void cpp_features_test_object_t::test<6>()
+{
+ DoNotCopy nc; // OK, default constructor
+ //DoNotCopy nc2(nc); // No, can't copy
+ //DoNotCopy nc3 = nc; // No, this also calls copy constructor (even though it looks like an assignment)
+}
+
+// defaulted function declaration
+//
+// https://en.cppreference.com/w/cpp/language/function#Function_definition
+//
+// What about the complementary case to the deleted function declaration, where you want a copy constructor
+// and are happy with the default implementation the compiler will make (memberwise copy).
+// Now you can explicitly declare that too.
+// Usage: I guess it makes the intent clearer, but otherwise not obviously useful.
+class DefaultCopyOK
+{
+public:
+ DefaultCopyOK() {}
+ DefaultCopyOK(const DefaultCopyOK&) = default;
+};
+
+template<> template<>
+void cpp_features_test_object_t::test<7>()
+{
+ DefaultCopyOK d; // OK
+ DefaultCopyOK d2(d); // OK
+ DefaultCopyOK d3 = d; // OK
+}
+
+
+} // namespace tut