summaryrefslogtreecommitdiff
path: root/chromium/third_party/openscreen/src/util
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2020-10-12 14:27:29 +0200
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2020-10-13 09:35:20 +0000
commitc30a6232df03e1efbd9f3b226777b07e087a1122 (patch)
treee992f45784689f373bcc38d1b79a239ebe17ee23 /chromium/third_party/openscreen/src/util
parent7b5b123ac58f58ffde0f4f6e488bcd09aa4decd3 (diff)
downloadqtwebengine-chromium-85-based.tar.gz
BASELINE: Update Chromium to 85.0.4183.14085-based
Change-Id: Iaa42f4680837c57725b1344f108c0196741f6057 Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
Diffstat (limited to 'chromium/third_party/openscreen/src/util')
-rw-r--r--chromium/third_party/openscreen/src/util/BUILD.gn3
-rw-r--r--chromium/third_party/openscreen/src/util/alarm_unittest.cc14
-rw-r--r--chromium/third_party/openscreen/src/util/big_endian.cc2
-rw-r--r--chromium/third_party/openscreen/src/util/big_endian.h2
-rw-r--r--chromium/third_party/openscreen/src/util/chrono_helpers.h50
-rw-r--r--chromium/third_party/openscreen/src/util/crypto/certificate_utils.cc13
-rw-r--r--chromium/third_party/openscreen/src/util/crypto/certificate_utils.h12
-rw-r--r--chromium/third_party/openscreen/src/util/crypto/secure_hash.h2
-rw-r--r--chromium/third_party/openscreen/src/util/json/json_helpers.h209
-rw-r--r--chromium/third_party/openscreen/src/util/json/json_helpers_unittest.cc209
-rw-r--r--chromium/third_party/openscreen/src/util/simple_fraction_unittest.cc16
-rw-r--r--chromium/third_party/openscreen/src/util/std_util.h30
-rw-r--r--chromium/third_party/openscreen/src/util/weak_ptr.h3
13 files changed, 524 insertions, 41 deletions
diff --git a/chromium/third_party/openscreen/src/util/BUILD.gn b/chromium/third_party/openscreen/src/util/BUILD.gn
index b21003462dc..000b3ea679c 100644
--- a/chromium/third_party/openscreen/src/util/BUILD.gn
+++ b/chromium/third_party/openscreen/src/util/BUILD.gn
@@ -23,6 +23,7 @@ source_set("util") {
"alarm.h",
"big_endian.cc",
"big_endian.h",
+ "chrono_helpers.h",
"crypto/certificate_utils.cc",
"crypto/certificate_utils.h",
"crypto/digest_sign.cc",
@@ -37,6 +38,7 @@ source_set("util") {
"crypto/sha2.h",
"hashing.h",
"integer_division.h",
+ "json/json_helpers.h",
"json/json_serialization.cc",
"json/json_serialization.h",
"json/json_value.cc",
@@ -86,6 +88,7 @@ source_set("unittests") {
"crypto/secure_hash_unittest.cc",
"crypto/sha2_unittest.cc",
"integer_division_unittest.cc",
+ "json/json_helpers_unittest.cc",
"json/json_serialization_unittest.cc",
"json/json_value_unittest.cc",
"operation_loop_unittest.cc",
diff --git a/chromium/third_party/openscreen/src/util/alarm_unittest.cc b/chromium/third_party/openscreen/src/util/alarm_unittest.cc
index 5fad74bf7f4..094afc9c42a 100644
--- a/chromium/third_party/openscreen/src/util/alarm_unittest.cc
+++ b/chromium/third_party/openscreen/src/util/alarm_unittest.cc
@@ -5,10 +5,12 @@
#include "util/alarm.h"
#include <algorithm>
+#include <chrono>
#include "gtest/gtest.h"
#include "platform/test/fake_clock.h"
#include "platform/test/fake_task_runner.h"
+#include "util/chrono_helpers.h"
namespace openscreen {
namespace {
@@ -26,7 +28,7 @@ class AlarmTest : public testing::Test {
};
TEST_F(AlarmTest, RunsTaskAsClockAdvances) {
- constexpr Clock::duration kDelay = std::chrono::milliseconds(20);
+ constexpr Clock::duration kDelay = milliseconds(20);
const Clock::time_point alarm_time = FakeClock::now() + kDelay;
Clock::time_point actual_run_time{};
@@ -61,12 +63,12 @@ TEST_F(AlarmTest, RunsTaskImmediately) {
ASSERT_EQ(expected_run_time, actual_run_time);
// Confirm the lambda is only run once.
- clock()->Advance(std::chrono::seconds(2));
+ clock()->Advance(seconds(2));
ASSERT_EQ(expected_run_time, actual_run_time);
}
TEST_F(AlarmTest, CancelsTaskWhenGoingOutOfScope) {
- constexpr Clock::duration kDelay = std::chrono::milliseconds(20);
+ constexpr Clock::duration kDelay = milliseconds(20);
constexpr Clock::time_point kNever{};
Clock::time_point actual_run_time{};
@@ -85,7 +87,7 @@ TEST_F(AlarmTest, CancelsTaskWhenGoingOutOfScope) {
}
TEST_F(AlarmTest, Cancels) {
- constexpr Clock::duration kDelay = std::chrono::milliseconds(20);
+ constexpr Clock::duration kDelay = milliseconds(20);
const Clock::time_point alarm_time = FakeClock::now() + kDelay;
Clock::time_point actual_run_time{};
@@ -104,8 +106,8 @@ TEST_F(AlarmTest, Cancels) {
}
TEST_F(AlarmTest, CancelsAndRearms) {
- constexpr Clock::duration kShorterDelay = std::chrono::milliseconds(10);
- constexpr Clock::duration kLongerDelay = std::chrono::milliseconds(100);
+ constexpr Clock::duration kShorterDelay = milliseconds(10);
+ constexpr Clock::duration kLongerDelay = milliseconds(100);
// Run the test twice: Once when scheduling first with a long delay, then a
// shorter delay; and once when scheduling first with a short delay, then a
diff --git a/chromium/third_party/openscreen/src/util/big_endian.cc b/chromium/third_party/openscreen/src/util/big_endian.cc
index d56589003ae..59992d605d4 100644
--- a/chromium/third_party/openscreen/src/util/big_endian.cc
+++ b/chromium/third_party/openscreen/src/util/big_endian.cc
@@ -30,4 +30,4 @@ bool BigEndianWriter::Write(const void* buffer, size_t length) {
return false;
}
-} // namespace openscreen \ No newline at end of file
+} // namespace openscreen
diff --git a/chromium/third_party/openscreen/src/util/big_endian.h b/chromium/third_party/openscreen/src/util/big_endian.h
index b2067d7537e..0953ddf08a6 100644
--- a/chromium/third_party/openscreen/src/util/big_endian.h
+++ b/chromium/third_party/openscreen/src/util/big_endian.h
@@ -150,7 +150,7 @@ class BigEndianBuffer {
public:
class Cursor {
public:
- Cursor(BigEndianBuffer* buffer)
+ explicit Cursor(BigEndianBuffer* buffer)
: buffer_(buffer), origin_(buffer_->current_) {}
Cursor(const Cursor& other) = delete;
Cursor(Cursor&& other) = delete;
diff --git a/chromium/third_party/openscreen/src/util/chrono_helpers.h b/chromium/third_party/openscreen/src/util/chrono_helpers.h
new file mode 100644
index 00000000000..a3711bbebb3
--- /dev/null
+++ b/chromium/third_party/openscreen/src/util/chrono_helpers.h
@@ -0,0 +1,50 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UTIL_CHRONO_HELPERS_H_
+#define UTIL_CHRONO_HELPERS_H_
+
+#include <chrono>
+
+// This file is a collection of helpful utilities and using statement for
+// working with std::chrono. In practice we previously defined these frequently,
+// this header allows for a single set of convenience statements.
+namespace openscreen {
+
+using hours = std::chrono::hours;
+using microseconds = std::chrono::microseconds;
+using milliseconds = std::chrono::milliseconds;
+using nanoseconds = std::chrono::nanoseconds;
+using seconds = std::chrono::seconds;
+
+// Casting statements. Note that duration_cast is not a type, it's a function,
+// so its behavior is different than the using statements above.
+template <typename D>
+static constexpr hours to_hours(D d) {
+ return std::chrono::duration_cast<hours>(d);
+}
+
+template <typename D>
+static constexpr microseconds to_microseconds(D d) {
+ return std::chrono::duration_cast<microseconds>(d);
+}
+
+template <typename D>
+static constexpr milliseconds to_milliseconds(D d) {
+ return std::chrono::duration_cast<milliseconds>(d);
+}
+
+template <typename D>
+static constexpr nanoseconds to_nanoseconds(D d) {
+ return std::chrono::duration_cast<nanoseconds>(d);
+}
+
+template <typename D>
+static constexpr seconds to_seconds(D d) {
+ return std::chrono::duration_cast<seconds>(d);
+}
+
+} // namespace openscreen
+
+#endif // UTIL_CHRONO_HELPERS_H_
diff --git a/chromium/third_party/openscreen/src/util/crypto/certificate_utils.cc b/chromium/third_party/openscreen/src/util/crypto/certificate_utils.cc
index ddedb533bb8..8f18b7ea9d8 100644
--- a/chromium/third_party/openscreen/src/util/crypto/certificate_utils.cc
+++ b/chromium/third_party/openscreen/src/util/crypto/certificate_utils.cc
@@ -146,19 +146,6 @@ ErrorOr<bssl::UniquePtr<X509>> CreateSelfSignedX509Certificate(
absl::string_view name,
std::chrono::seconds duration,
const EVP_PKEY& key_pair,
- std::chrono::seconds time_since_unix_epoch) {
- bssl::UniquePtr<X509> certificate = CreateCertificateInternal(
- name, duration, key_pair, time_since_unix_epoch, false, nullptr, nullptr);
- if (!certificate) {
- return Error::Code::kCertificateCreationError;
- }
- return certificate;
-}
-
-ErrorOr<bssl::UniquePtr<X509>> CreateSelfSignedX509CertificateForTest(
- absl::string_view name,
- std::chrono::seconds duration,
- const EVP_PKEY& key_pair,
std::chrono::seconds time_since_unix_epoch,
bool make_ca,
X509* issuer,
diff --git a/chromium/third_party/openscreen/src/util/crypto/certificate_utils.h b/chromium/third_party/openscreen/src/util/crypto/certificate_utils.h
index e60c28c3d26..22da0330a0b 100644
--- a/chromium/third_party/openscreen/src/util/crypto/certificate_utils.h
+++ b/chromium/third_party/openscreen/src/util/crypto/certificate_utils.h
@@ -23,22 +23,12 @@ namespace openscreen {
// Generates a new RSA key pair with bit width |key_bits|.
bssl::UniquePtr<EVP_PKEY> GenerateRsaKeyPair(int key_bits = 2048);
-// Creates a new self-signed X509 certificate having the given |name| and
-// |duration| until expiration, and based on the given |key_pair|, which is
-// expected to contain a valid private key.
-// |time_since_unix_epoch| is the current time.
-ErrorOr<bssl::UniquePtr<X509>> CreateSelfSignedX509Certificate(
- absl::string_view name,
- std::chrono::seconds duration,
- const EVP_PKEY& key_pair,
- std::chrono::seconds time_since_unix_epoch = GetWallTimeSinceUnixEpoch());
-
// Creates a new X509 certificate having the given |name| and |duration| until
// expiration, and based on the given |key_pair|. If |issuer| and |issuer_key|
// are provided, they are used to set the issuer information, otherwise it will
// be self-signed. |make_ca| determines whether additional extensions are added
// to make it a valid certificate authority cert.
-ErrorOr<bssl::UniquePtr<X509>> CreateSelfSignedX509CertificateForTest(
+ErrorOr<bssl::UniquePtr<X509>> CreateSelfSignedX509Certificate(
absl::string_view name,
std::chrono::seconds duration,
const EVP_PKEY& key_pair,
diff --git a/chromium/third_party/openscreen/src/util/crypto/secure_hash.h b/chromium/third_party/openscreen/src/util/crypto/secure_hash.h
index 7c007f96350..f748cc458b5 100644
--- a/chromium/third_party/openscreen/src/util/crypto/secure_hash.h
+++ b/chromium/third_party/openscreen/src/util/crypto/secure_hash.h
@@ -21,7 +21,7 @@ namespace openscreen {
// same as if we have the full input in advance.
class SecureHash {
public:
- SecureHash(const EVP_MD* type);
+ explicit SecureHash(const EVP_MD* type);
SecureHash(const SecureHash& other);
SecureHash(SecureHash&& other);
SecureHash& operator=(const SecureHash& other);
diff --git a/chromium/third_party/openscreen/src/util/json/json_helpers.h b/chromium/third_party/openscreen/src/util/json/json_helpers.h
new file mode 100644
index 00000000000..a4c43479edc
--- /dev/null
+++ b/chromium/third_party/openscreen/src/util/json/json_helpers.h
@@ -0,0 +1,209 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UTIL_JSON_JSON_HELPERS_H_
+#define UTIL_JSON_JSON_HELPERS_H_
+
+#include <chrono>
+#include <functional>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "absl/strings/string_view.h"
+#include "json/value.h"
+#include "platform/base/error.h"
+#include "util/chrono_helpers.h"
+#include "util/simple_fraction.h"
+
+// This file contains helper methods for parsing JSON, in an attempt to
+// reduce boilerplate code when working with JsonCpp.
+namespace openscreen {
+namespace json {
+
+// TODO(jophba): remove these methods after refactoring offer messaging.
+inline Error CreateParseError(const std::string& type) {
+ return Error(Error::Code::kJsonParseError, "Failed to parse " + type);
+}
+
+inline Error CreateParameterError(const std::string& type) {
+ return Error(Error::Code::kParameterInvalid, "Invalid parameter: " + type);
+}
+
+inline ErrorOr<bool> ParseBool(const Json::Value& parent,
+ const std::string& field) {
+ const Json::Value& value = parent[field];
+ if (!value.isBool()) {
+ return CreateParseError("bool field " + field);
+ }
+ return value.asBool();
+}
+
+inline ErrorOr<int> ParseInt(const Json::Value& parent,
+ const std::string& field) {
+ const Json::Value& value = parent[field];
+ if (!value.isInt()) {
+ return CreateParseError("integer field: " + field);
+ }
+ return value.asInt();
+}
+
+inline ErrorOr<uint32_t> ParseUint(const Json::Value& parent,
+ const std::string& field) {
+ const Json::Value& value = parent[field];
+ if (!value.isUInt()) {
+ return CreateParseError("unsigned integer field: " + field);
+ }
+ return value.asUInt();
+}
+
+inline ErrorOr<std::string> ParseString(const Json::Value& parent,
+ const std::string& field) {
+ const Json::Value& value = parent[field];
+ if (!value.isString()) {
+ return CreateParseError("string field: " + field);
+ }
+ return value.asString();
+}
+
+// TODO(jophba): offer messaging should use these methods instead.
+inline bool ParseBool(const Json::Value& value, bool* out) {
+ if (!value.isBool()) {
+ return false;
+ }
+ *out = value.asBool();
+ return true;
+}
+
+// A general note about parsing primitives. "Validation" in this context
+// generally means ensuring that the values are non-negative. There are
+// currently no cases in our usage of JSON strings where we accept negative
+// values. If this changes in the future, care must be taken to ensure
+// that we don't break anything in existing code.
+inline bool ParseAndValidateDouble(const Json::Value& value, double* out) {
+ if (!value.isDouble()) {
+ return false;
+ }
+ const double d = value.asDouble();
+ if (d < 0) {
+ return false;
+ }
+ *out = d;
+ return true;
+}
+
+inline bool ParseAndValidateInt(const Json::Value& value, int* out) {
+ if (!value.isInt()) {
+ return false;
+ }
+ int i = value.asInt();
+ if (i < 0) {
+ return false;
+ }
+ *out = i;
+ return true;
+}
+
+inline bool ParseAndValidateUint(const Json::Value& value, uint32_t* out) {
+ if (!value.isUInt()) {
+ return false;
+ }
+ *out = value.asUInt();
+ return true;
+}
+
+inline bool ParseAndValidateString(const Json::Value& value, std::string* out) {
+ if (!value.isString()) {
+ return false;
+ }
+ *out = value.asString();
+ return true;
+}
+
+// We want to be more robust when we parse fractions then just
+// allowing strings, this will parse numeral values such as
+// value: 50 as well as value: "50" and value: "100/2".
+inline bool ParseAndValidateSimpleFraction(const Json::Value& value,
+ SimpleFraction* out) {
+ if (value.isInt()) {
+ int parsed = value.asInt();
+ if (parsed < 0) {
+ return false;
+ }
+ *out = SimpleFraction{parsed, 1};
+ return true;
+ }
+
+ if (value.isString()) {
+ auto fraction_or_error = SimpleFraction::FromString(value.asString());
+ if (!fraction_or_error) {
+ return false;
+ }
+
+ if (!fraction_or_error.value().is_positive() ||
+ !fraction_or_error.value().is_defined()) {
+ return false;
+ }
+ *out = std::move(fraction_or_error.value());
+ return true;
+ }
+ return false;
+}
+
+inline bool ParseAndValidateMilliseconds(const Json::Value& value,
+ milliseconds* out) {
+ int out_ms;
+ if (!ParseAndValidateInt(value, &out_ms) || out_ms < 0) {
+ return false;
+ }
+ *out = milliseconds(out_ms);
+ return true;
+}
+
+template <typename T>
+using Parser = std::function<bool(const Json::Value&, T*)>;
+
+// NOTE: array parsing methods reset the output vector to an empty vector in
+// any error case. This is especially useful for optional arrays.
+template <typename T>
+bool ParseAndValidateArray(const Json::Value& value,
+ Parser<T> parser,
+ std::vector<T>* out) {
+ out->clear();
+ if (!value.isArray() || value.empty()) {
+ return false;
+ }
+
+ out->reserve(value.size());
+ for (Json::ArrayIndex i = 0; i < value.size(); ++i) {
+ T v;
+ if (!parser(value[i], &v)) {
+ out->clear();
+ return false;
+ }
+ out->push_back(v);
+ }
+
+ return true;
+}
+
+inline bool ParseAndValidateIntArray(const Json::Value& value,
+ std::vector<int>* out) {
+ return ParseAndValidateArray<int>(value, ParseAndValidateInt, out);
+}
+
+inline bool ParseAndValidateUintArray(const Json::Value& value,
+ std::vector<uint32_t>* out) {
+ return ParseAndValidateArray<uint32_t>(value, ParseAndValidateUint, out);
+}
+
+inline bool ParseAndValidateStringArray(const Json::Value& value,
+ std::vector<std::string>* out) {
+ return ParseAndValidateArray<std::string>(value, ParseAndValidateString, out);
+}
+
+} // namespace json
+} // namespace openscreen
+
+#endif // UTIL_JSON_JSON_HELPERS_H_
diff --git a/chromium/third_party/openscreen/src/util/json/json_helpers_unittest.cc b/chromium/third_party/openscreen/src/util/json/json_helpers_unittest.cc
new file mode 100644
index 00000000000..fdac1897e4b
--- /dev/null
+++ b/chromium/third_party/openscreen/src/util/json/json_helpers_unittest.cc
@@ -0,0 +1,209 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "util/json/json_helpers.h"
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include "util/chrono_helpers.h"
+
+namespace openscreen {
+namespace json {
+namespace {
+
+using ::testing::ElementsAre;
+
+const Json::Value kNone;
+const Json::Value kEmptyString = "";
+const Json::Value kEmptyArray(Json::arrayValue);
+
+struct Dummy {
+ int value;
+
+ constexpr bool operator==(const Dummy& other) const {
+ return other.value == value;
+ }
+};
+
+bool ParseAndValidateDummy(const Json::Value& value, Dummy* out) {
+ int value_out;
+ if (!ParseAndValidateInt(value, &value_out)) {
+ return false;
+ }
+ *out = Dummy{value_out};
+ return true;
+}
+
+} // namespace
+
+TEST(ParsingHelpersTest, ParseAndValidateDouble) {
+ const Json::Value kValid = 13.37;
+ const Json::Value kNotDouble = "coffee beans";
+ const Json::Value kNegativeDouble = -4.2;
+ const Json::Value kZeroDouble = 0.0;
+
+ double out;
+ EXPECT_TRUE(ParseAndValidateDouble(kValid, &out));
+ EXPECT_DOUBLE_EQ(13.37, out);
+ EXPECT_TRUE(ParseAndValidateDouble(kZeroDouble, &out));
+ EXPECT_DOUBLE_EQ(0.0, out);
+ EXPECT_FALSE(ParseAndValidateDouble(kNotDouble, &out));
+ EXPECT_FALSE(ParseAndValidateDouble(kNegativeDouble, &out));
+ EXPECT_FALSE(ParseAndValidateDouble(kNone, &out));
+}
+
+TEST(ParsingHelpersTest, ParseAndValidateInt) {
+ const Json::Value kValid = 1337;
+ const Json::Value kNotInt = "cold brew";
+ const Json::Value kNegativeInt = -42;
+ const Json::Value kZeroInt = 0;
+
+ int out;
+ EXPECT_TRUE(ParseAndValidateInt(kValid, &out));
+ EXPECT_EQ(1337, out);
+ EXPECT_TRUE(ParseAndValidateInt(kZeroInt, &out));
+ EXPECT_EQ(0, out);
+ EXPECT_FALSE(ParseAndValidateInt(kNone, &out));
+ EXPECT_FALSE(ParseAndValidateInt(kNotInt, &out));
+ EXPECT_FALSE(ParseAndValidateInt(kNegativeInt, &out));
+}
+
+TEST(ParsingHelpersTest, ParseAndValidateUint) {
+ const Json::Value kValid = 1337u;
+ const Json::Value kNotUint = "espresso";
+ const Json::Value kZeroUint = 0u;
+
+ uint32_t out;
+ EXPECT_TRUE(ParseAndValidateUint(kValid, &out));
+ EXPECT_EQ(1337u, out);
+ EXPECT_TRUE(ParseAndValidateUint(kZeroUint, &out));
+ EXPECT_EQ(0u, out);
+ EXPECT_FALSE(ParseAndValidateUint(kNone, &out));
+ EXPECT_FALSE(ParseAndValidateUint(kNotUint, &out));
+}
+
+TEST(ParsingHelpersTest, ParseAndValidateString) {
+ const Json::Value kValid = "macchiato";
+ const Json::Value kNotString = 42;
+
+ std::string out;
+ EXPECT_TRUE(ParseAndValidateString(kValid, &out));
+ EXPECT_EQ("macchiato", out);
+ EXPECT_TRUE(ParseAndValidateString(kEmptyString, &out));
+ EXPECT_EQ("", out);
+ EXPECT_FALSE(ParseAndValidateString(kNone, &out));
+ EXPECT_FALSE(ParseAndValidateString(kNotString, &out));
+}
+
+// Simple fraction validity is tested extensively in its unit tests, so we
+// just check the major cases here.
+TEST(ParsingHelpersTest, ParseAndValidateSimpleFraction) {
+ const Json::Value kValid = "42/30";
+ const Json::Value kValidNumber = "42";
+ const Json::Value kUndefined = "5/0";
+ const Json::Value kNegative = "10/-2";
+ const Json::Value kInvalidNumber = "-1";
+ const Json::Value kNotSimpleFraction = "latte";
+
+ SimpleFraction out;
+ EXPECT_TRUE(ParseAndValidateSimpleFraction(kValid, &out));
+ EXPECT_EQ((SimpleFraction{42, 30}), out);
+ EXPECT_TRUE(ParseAndValidateSimpleFraction(kValidNumber, &out));
+ EXPECT_EQ((SimpleFraction{42, 1}), out);
+ EXPECT_FALSE(ParseAndValidateSimpleFraction(kUndefined, &out));
+ EXPECT_FALSE(ParseAndValidateSimpleFraction(kNegative, &out));
+ EXPECT_FALSE(ParseAndValidateSimpleFraction(kInvalidNumber, &out));
+ EXPECT_FALSE(ParseAndValidateSimpleFraction(kNotSimpleFraction, &out));
+ EXPECT_FALSE(ParseAndValidateSimpleFraction(kNone, &out));
+ EXPECT_FALSE(ParseAndValidateSimpleFraction(kEmptyString, &out));
+}
+
+TEST(ParsingHelpersTest, ParseAndValidateMilliseconds) {
+ const Json::Value kValid = 1000;
+ const Json::Value kValidFloat = 500.0;
+ const Json::Value kNegativeNumber = -120;
+ const Json::Value kZeroNumber = 0;
+ const Json::Value kNotNumber = "affogato";
+
+ milliseconds out;
+ EXPECT_TRUE(ParseAndValidateMilliseconds(kValid, &out));
+ EXPECT_EQ(milliseconds(1000), out);
+ EXPECT_TRUE(ParseAndValidateMilliseconds(kValidFloat, &out));
+ EXPECT_EQ(milliseconds(500), out);
+ EXPECT_TRUE(ParseAndValidateMilliseconds(kZeroNumber, &out));
+ EXPECT_EQ(milliseconds(0), out);
+ EXPECT_FALSE(ParseAndValidateMilliseconds(kNone, &out));
+ EXPECT_FALSE(ParseAndValidateMilliseconds(kNegativeNumber, &out));
+ EXPECT_FALSE(ParseAndValidateMilliseconds(kNotNumber, &out));
+}
+
+TEST(ParsingHelpersTest, ParseAndValidateArray) {
+ Json::Value valid_dummy_array;
+ valid_dummy_array[0] = 123;
+ valid_dummy_array[1] = 456;
+
+ Json::Value invalid_dummy_array;
+ invalid_dummy_array[0] = "iced coffee";
+ invalid_dummy_array[1] = 456;
+
+ std::vector<Dummy> out;
+ EXPECT_TRUE(ParseAndValidateArray<Dummy>(valid_dummy_array,
+ ParseAndValidateDummy, &out));
+ EXPECT_THAT(out, ElementsAre(Dummy{123}, Dummy{456}));
+ EXPECT_FALSE(ParseAndValidateArray<Dummy>(invalid_dummy_array,
+ ParseAndValidateDummy, &out));
+ EXPECT_FALSE(
+ ParseAndValidateArray<Dummy>(kEmptyArray, ParseAndValidateDummy, &out));
+}
+
+TEST(ParsingHelpersTest, ParseAndValidateIntArray) {
+ Json::Value valid_int_array;
+ valid_int_array[0] = 123;
+ valid_int_array[1] = 456;
+
+ Json::Value invalid_int_array;
+ invalid_int_array[0] = "iced coffee";
+ invalid_int_array[1] = 456;
+
+ std::vector<int> out;
+ EXPECT_TRUE(ParseAndValidateIntArray(valid_int_array, &out));
+ EXPECT_THAT(out, ElementsAre(123, 456));
+ EXPECT_FALSE(ParseAndValidateIntArray(invalid_int_array, &out));
+ EXPECT_FALSE(ParseAndValidateIntArray(kEmptyArray, &out));
+}
+
+TEST(ParsingHelpersTest, ParseAndValidateUintArray) {
+ Json::Value valid_uint_array;
+ valid_uint_array[0] = 123u;
+ valid_uint_array[1] = 456u;
+
+ Json::Value invalid_uint_array;
+ invalid_uint_array[0] = "breve";
+ invalid_uint_array[1] = 456u;
+
+ std::vector<uint32_t> out;
+ EXPECT_TRUE(ParseAndValidateUintArray(valid_uint_array, &out));
+ EXPECT_THAT(out, ElementsAre(123u, 456u));
+ EXPECT_FALSE(ParseAndValidateUintArray(invalid_uint_array, &out));
+ EXPECT_FALSE(ParseAndValidateUintArray(kEmptyArray, &out));
+}
+
+TEST(ParsingHelpersTest, ParseAndValidateStringArray) {
+ Json::Value valid_string_array;
+ valid_string_array[0] = "nitro cold brew";
+ valid_string_array[1] = "doppio espresso";
+
+ Json::Value invalid_string_array;
+ invalid_string_array[0] = "mocha latte";
+ invalid_string_array[1] = 456;
+
+ std::vector<std::string> out;
+ EXPECT_TRUE(ParseAndValidateStringArray(valid_string_array, &out));
+ EXPECT_THAT(out, ElementsAre("nitro cold brew", "doppio espresso"));
+ EXPECT_FALSE(ParseAndValidateStringArray(invalid_string_array, &out));
+ EXPECT_FALSE(ParseAndValidateStringArray(kEmptyArray, &out));
+}
+
+} // namespace json
+} // namespace openscreen
diff --git a/chromium/third_party/openscreen/src/util/simple_fraction_unittest.cc b/chromium/third_party/openscreen/src/util/simple_fraction_unittest.cc
index 7cdbfeeccad..49bf3987df1 100644
--- a/chromium/third_party/openscreen/src/util/simple_fraction_unittest.cc
+++ b/chromium/third_party/openscreen/src/util/simple_fraction_unittest.cc
@@ -4,6 +4,7 @@
#include "util/simple_fraction.h"
+#include <cmath>
#include <limits>
#include "gtest/gtest.h"
@@ -15,16 +16,15 @@ namespace {
constexpr int kMin = std::numeric_limits<int>::min();
constexpr int kMax = std::numeric_limits<int>::max();
-void ExpectFromStringEquals(absl::string_view s,
- const SimpleFraction& expected) {
- const ErrorOr<SimpleFraction> f = SimpleFraction::FromString(s);
- EXPECT_TRUE(f.is_value());
+void ExpectFromStringEquals(const char* s, const SimpleFraction& expected) {
+ const ErrorOr<SimpleFraction> f = SimpleFraction::FromString(std::string(s));
+ EXPECT_TRUE(f.is_value()) << "from string: '" << s << "'";
EXPECT_EQ(expected, f.value());
}
-void ExpectFromStringError(absl::string_view s) {
- const auto f = SimpleFraction::FromString(s);
- EXPECT_TRUE(f.is_error());
+void ExpectFromStringError(const char* s) {
+ const auto f = SimpleFraction::FromString(std::string(s));
+ EXPECT_TRUE(f.is_error()) << "from string: '" << s << "'";
}
} // namespace
@@ -46,6 +46,7 @@ TEST(SimpleFractionTest, FromStringErrorsOnInvalid) {
ExpectFromStringError("1/");
ExpectFromStringError("/1");
ExpectFromStringError("888/");
+ ExpectFromStringError("1/2/3");
ExpectFromStringError("not a fraction at all");
}
@@ -91,6 +92,7 @@ TEST(SimpleFractionTest, Positivity) {
TEST(SimpleFractionTest, CastToDouble) {
EXPECT_DOUBLE_EQ(0.0, static_cast<double>(SimpleFraction{0, 1}));
EXPECT_DOUBLE_EQ(1.0, static_cast<double>(SimpleFraction{1, 1}));
+ EXPECT_TRUE(std::isnan(static_cast<double>(SimpleFraction{1, 0})));
EXPECT_DOUBLE_EQ(1.0, static_cast<double>(SimpleFraction{kMax, kMax}));
EXPECT_DOUBLE_EQ(1.0, static_cast<double>(SimpleFraction{kMin, kMin}));
}
diff --git a/chromium/third_party/openscreen/src/util/std_util.h b/chromium/third_party/openscreen/src/util/std_util.h
index 5a77bb5513a..87726955f94 100644
--- a/chromium/third_party/openscreen/src/util/std_util.h
+++ b/chromium/third_party/openscreen/src/util/std_util.h
@@ -5,8 +5,10 @@
#ifndef UTIL_STD_UTIL_H_
#define UTIL_STD_UTIL_H_
+#include <algorithm>
#include <map>
#include <string>
+#include <utility>
#include <vector>
#include "absl/algorithm/container.h"
@@ -53,6 +55,34 @@ void SortAndDedupeElements(RandomAccessContainer* c) {
c->erase(new_end, c->end());
}
+// Append the provided elements together into a single vector. This can be
+// useful when creating a vector of variadic templates in the ctor.
+//
+// This is the base case for the recursion
+template <typename T>
+std::vector<T>&& Append(std::vector<T>&& so_far) {
+ return std::move(so_far);
+}
+
+// This is the recursive call. Depending on the number of remaining elements, it
+// either calls into itself or into the above base case.
+template <typename T, typename TFirst, typename... TOthers>
+std::vector<T>&& Append(std::vector<T>&& so_far,
+ TFirst&& new_element,
+ TOthers&&... new_elements) {
+ so_far.push_back(std::move(new_element));
+ return Append(std::move(so_far), std::move(new_elements)...);
+}
+
+// Creates an empty vector with |size| elements reserved. Intended to be used as
+// GetEmptyVectorOfSize<T>(sizeof...(variadic_input))
+template <typename T>
+std::vector<T> GetVectorWithCapacity(size_t size) {
+ std::vector<T> results;
+ results.reserve(size);
+ return results;
+}
+
} // namespace openscreen
#endif // UTIL_STD_UTIL_H_
diff --git a/chromium/third_party/openscreen/src/util/weak_ptr.h b/chromium/third_party/openscreen/src/util/weak_ptr.h
index cb6967a1d59..c941017d511 100644
--- a/chromium/third_party/openscreen/src/util/weak_ptr.h
+++ b/chromium/third_party/openscreen/src/util/weak_ptr.h
@@ -6,6 +6,7 @@
#define UTIL_WEAK_PTR_H_
#include <memory>
+#include <utility>
#include "util/osp_logging.h"
@@ -92,7 +93,7 @@ class WeakPtr {
}
// Create/Assign from nullptr.
- WeakPtr(std::nullptr_t) {}
+ WeakPtr(std::nullptr_t) {} // NOLINT
WeakPtr& operator=(std::nullptr_t) {
impl_.reset();