Adding RTCErrorOr class to be used by ORTC APIs.
This utility class can be used to represent either an error or a successful return value. Follows the pattern of StatusOr in the protobuf library. This will be used by ORTC factory methods; for instance, CreateRtpSender will either return an RtpSender or an error if the parameters are invalid or some other failure occurs. This CL also moves RTCError classes to a separate file, and adds tests that were missing before. BUG=webrtc:7013 Review-Url: https://codereview.webrtc.org/2692723002 Cr-Commit-Position: refs/heads/master@{#16659}
This commit is contained in:
parent
74520c6718
commit
6038e97e04
@ -287,6 +287,7 @@ if (!build_with_chromium) {
|
||||
":video_engine_tests",
|
||||
":webrtc_nonparallel_tests",
|
||||
":webrtc_perf_tests",
|
||||
"api:rtc_api_unittests",
|
||||
"base:rtc_base_tests_utils",
|
||||
"common_audio:common_audio_unittests",
|
||||
"common_video:common_video_unittests",
|
||||
|
||||
@ -61,6 +61,8 @@ rtc_static_library("libjingle_peerconnection_api") {
|
||||
"peerconnectioninterface.h",
|
||||
"peerconnectionproxy.h",
|
||||
"proxy.h",
|
||||
"rtcerror.cc",
|
||||
"rtcerror.h",
|
||||
"rtpparameters.h",
|
||||
"rtpreceiverinterface.h",
|
||||
"rtpsender.h",
|
||||
@ -198,4 +200,29 @@ if (rtc_include_tests) {
|
||||
suppressed_configs += [ "//build/config/clang:find_bad_constructs" ]
|
||||
}
|
||||
}
|
||||
|
||||
rtc_test("rtc_api_unittests") {
|
||||
testonly = true
|
||||
|
||||
sources = [
|
||||
"rtcerror_unittest.cc",
|
||||
]
|
||||
|
||||
if (!build_with_chromium && is_clang) {
|
||||
# Suppress warnings from the Chromium Clang plugin (bugs.webrtc.org/163).
|
||||
suppressed_configs += [ "//build/config/clang:find_bad_constructs" ]
|
||||
}
|
||||
|
||||
deps = [
|
||||
":libjingle_peerconnection_api",
|
||||
"../base:rtc_base_tests_main",
|
||||
"../base:rtc_base_tests_utils",
|
||||
"../system_wrappers:metrics_default",
|
||||
"../test:test_support",
|
||||
]
|
||||
|
||||
if (is_android) {
|
||||
deps += [ "//testing/android/native_test:native_test_support" ]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -78,6 +78,7 @@
|
||||
#include "webrtc/api/dtmfsenderinterface.h"
|
||||
#include "webrtc/api/jsep.h"
|
||||
#include "webrtc/api/mediastreaminterface.h"
|
||||
#include "webrtc/api/rtcerror.h"
|
||||
#include "webrtc/api/rtpreceiverinterface.h"
|
||||
#include "webrtc/api/rtpsenderinterface.h"
|
||||
#include "webrtc/api/stats/rtcstatscollectorcallback.h"
|
||||
@ -133,62 +134,6 @@ class StatsObserver : public rtc::RefCountInterface {
|
||||
virtual ~StatsObserver() {}
|
||||
};
|
||||
|
||||
// Enumeration to represent distinct classes of errors that an application
|
||||
// may wish to act upon differently. These roughly map to DOMExceptions or
|
||||
// RTCError "errorDetailEnum" values in the web API, as described in the
|
||||
// comments below.
|
||||
enum class RTCErrorType {
|
||||
// No error.
|
||||
NONE,
|
||||
// A supplied parameter is valid, but currently unsupported.
|
||||
// Maps to InvalidAccessError DOMException.
|
||||
UNSUPPORTED_PARAMETER,
|
||||
// General error indicating that a supplied parameter is invalid.
|
||||
// Maps to InvalidAccessError or TypeError DOMException depending on context.
|
||||
INVALID_PARAMETER,
|
||||
// Slightly more specific than INVALID_PARAMETER; a parameter's value was
|
||||
// outside the allowed range.
|
||||
// Maps to RangeError DOMException.
|
||||
INVALID_RANGE,
|
||||
// Slightly more specific than INVALID_PARAMETER; an error occurred while
|
||||
// parsing string input.
|
||||
// Maps to SyntaxError DOMException.
|
||||
SYNTAX_ERROR,
|
||||
// The object does not support this operation in its current state.
|
||||
// Maps to InvalidStateError DOMException.
|
||||
INVALID_STATE,
|
||||
// An attempt was made to modify the object in an invalid way.
|
||||
// Maps to InvalidModificationError DOMException.
|
||||
INVALID_MODIFICATION,
|
||||
// An error occurred within an underlying network protocol.
|
||||
// Maps to NetworkError DOMException.
|
||||
NETWORK_ERROR,
|
||||
// The operation failed due to an internal error.
|
||||
// Maps to OperationError DOMException.
|
||||
INTERNAL_ERROR,
|
||||
};
|
||||
|
||||
// Roughly corresponds to RTCError in the web api. Holds an error type and
|
||||
// possibly additional information specific to that error.
|
||||
//
|
||||
// Doesn't contain anything beyond a type now, but will in the future as more
|
||||
// errors are implemented.
|
||||
class RTCError {
|
||||
public:
|
||||
RTCError() : type_(RTCErrorType::NONE) {}
|
||||
explicit RTCError(RTCErrorType type) : type_(type) {}
|
||||
|
||||
RTCErrorType type() const { return type_; }
|
||||
void set_type(RTCErrorType type) { type_ = type; }
|
||||
|
||||
private:
|
||||
RTCErrorType type_;
|
||||
};
|
||||
|
||||
// Outputs the error as a friendly string.
|
||||
// Update this method when adding a new error type.
|
||||
std::ostream& operator<<(std::ostream& stream, RTCErrorType error);
|
||||
|
||||
class PeerConnectionInterface : public rtc::RefCountInterface {
|
||||
public:
|
||||
// See http://dev.w3.org/2011/webrtc/editor/webrtc.html#state-definitions .
|
||||
|
||||
101
webrtc/api/rtcerror.cc
Normal file
101
webrtc/api/rtcerror.cc
Normal file
@ -0,0 +1,101 @@
|
||||
/*
|
||||
* Copyright 2017 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "webrtc/api/rtcerror.h"
|
||||
|
||||
#include "webrtc/base/arraysize.h"
|
||||
|
||||
namespace {
|
||||
|
||||
static const char* const kRTCErrorTypeNames[] = {
|
||||
"NONE",
|
||||
"UNSUPPORTED_OPERATION",
|
||||
"UNSUPPORTED_PARAMETER",
|
||||
"INVALID_PARAMETER",
|
||||
"INVALID_RANGE",
|
||||
"SYNTAX_ERROR",
|
||||
"INVALID_STATE",
|
||||
"INVALID_MODIFICATION",
|
||||
"NETWORK_ERROR",
|
||||
"RESOURCE_EXHAUSTED",
|
||||
"INTERNAL_ERROR",
|
||||
};
|
||||
static_assert(static_cast<int>(webrtc::RTCErrorType::INTERNAL_ERROR) ==
|
||||
(arraysize(kRTCErrorTypeNames) - 1),
|
||||
"kRTCErrorTypeNames must have as many strings as RTCErrorType "
|
||||
"has values.");
|
||||
|
||||
} // namespace
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
RTCError::RTCError(RTCError&& other)
|
||||
: type_(other.type_), have_string_message_(other.have_string_message_) {
|
||||
if (have_string_message_) {
|
||||
new (&string_message_) std::string(std::move(other.string_message_));
|
||||
} else {
|
||||
static_message_ = other.static_message_;
|
||||
}
|
||||
}
|
||||
|
||||
RTCError& RTCError::operator=(RTCError&& other) {
|
||||
type_ = other.type_;
|
||||
if (other.have_string_message_) {
|
||||
set_message(std::move(other.string_message_));
|
||||
} else {
|
||||
set_message(other.static_message_);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
RTCError::~RTCError() {
|
||||
// If we hold a message string that was built, rather than a static string,
|
||||
// we need to delete it.
|
||||
if (have_string_message_) {
|
||||
string_message_.~basic_string();
|
||||
}
|
||||
}
|
||||
|
||||
// static
|
||||
RTCError RTCError::OK() {
|
||||
return RTCError();
|
||||
}
|
||||
|
||||
const char* RTCError::message() const {
|
||||
if (have_string_message_) {
|
||||
return string_message_.c_str();
|
||||
} else {
|
||||
return static_message_;
|
||||
}
|
||||
}
|
||||
|
||||
void RTCError::set_message(const char* message) {
|
||||
if (have_string_message_) {
|
||||
string_message_.~basic_string();
|
||||
have_string_message_ = false;
|
||||
}
|
||||
static_message_ = message;
|
||||
}
|
||||
|
||||
void RTCError::set_message(std::string&& message) {
|
||||
if (!have_string_message_) {
|
||||
new (&string_message_) std::string(std::move(message));
|
||||
have_string_message_ = true;
|
||||
} else {
|
||||
string_message_ = message;
|
||||
}
|
||||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream& stream, RTCErrorType error) {
|
||||
int index = static_cast<int>(error);
|
||||
return stream << kRTCErrorTypeNames[index];
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
||||
291
webrtc/api/rtcerror.h
Normal file
291
webrtc/api/rtcerror.h
Normal file
@ -0,0 +1,291 @@
|
||||
/*
|
||||
* Copyright 2017 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef WEBRTC_API_RTCERROR_H_
|
||||
#define WEBRTC_API_RTCERROR_H_
|
||||
|
||||
#include <ostream>
|
||||
#include <string>
|
||||
#include <utility> // For std::move.
|
||||
|
||||
#include "webrtc/base/checks.h"
|
||||
#include "webrtc/base/logging.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
// Enumeration to represent distinct classes of errors that an application
|
||||
// may wish to act upon differently. These roughly map to DOMExceptions or
|
||||
// RTCError "errorDetailEnum" values in the web API, as described in the
|
||||
// comments below.
|
||||
enum class RTCErrorType {
|
||||
// No error.
|
||||
NONE,
|
||||
|
||||
// An operation is valid, but currently unsupported.
|
||||
// Maps to OperationError DOMException.
|
||||
UNSUPPORTED_OPERATION,
|
||||
|
||||
// A supplied parameter is valid, but currently unsupported.
|
||||
// Maps to OperationError DOMException.
|
||||
UNSUPPORTED_PARAMETER,
|
||||
|
||||
// General error indicating that a supplied parameter is invalid.
|
||||
// Maps to InvalidAccessError or TypeError DOMException depending on context.
|
||||
INVALID_PARAMETER,
|
||||
|
||||
// Slightly more specific than INVALID_PARAMETER; a parameter's value was
|
||||
// outside the allowed range.
|
||||
// Maps to RangeError DOMException.
|
||||
INVALID_RANGE,
|
||||
|
||||
// Slightly more specific than INVALID_PARAMETER; an error occurred while
|
||||
// parsing string input.
|
||||
// Maps to SyntaxError DOMException.
|
||||
SYNTAX_ERROR,
|
||||
|
||||
// The object does not support this operation in its current state.
|
||||
// Maps to InvalidStateError DOMException.
|
||||
INVALID_STATE,
|
||||
|
||||
// An attempt was made to modify the object in an invalid way.
|
||||
// Maps to InvalidModificationError DOMException.
|
||||
INVALID_MODIFICATION,
|
||||
|
||||
// An error occurred within an underlying network protocol.
|
||||
// Maps to NetworkError DOMException.
|
||||
NETWORK_ERROR,
|
||||
|
||||
// Some resource has been exhausted; file handles, hardware resources, ports,
|
||||
// etc.
|
||||
// Maps to OperationError DOMException.
|
||||
RESOURCE_EXHAUSTED,
|
||||
|
||||
// The operation failed due to an internal error.
|
||||
// Maps to OperationError DOMException.
|
||||
INTERNAL_ERROR,
|
||||
};
|
||||
|
||||
// Roughly corresponds to RTCError in the web api. Holds an error type, a
|
||||
// message, and possibly additional information specific to that error.
|
||||
//
|
||||
// Doesn't contain anything beyond a type and message now, but will in the
|
||||
// future as more errors are implemented.
|
||||
class RTCError {
|
||||
public:
|
||||
// Constructors.
|
||||
|
||||
// Creates a "no error" error.
|
||||
RTCError() {}
|
||||
explicit RTCError(RTCErrorType type) : type_(type) {}
|
||||
// For performance, prefer using the constructor that takes a const char* if
|
||||
// the message is a static string.
|
||||
RTCError(RTCErrorType type, const char* message)
|
||||
: type_(type), static_message_(message), have_string_message_(false) {}
|
||||
RTCError(RTCErrorType type, std::string&& message)
|
||||
: type_(type), string_message_(message), have_string_message_(true) {}
|
||||
|
||||
// Delete the copy constructor and assignment operator; there aren't any use
|
||||
// cases where you should need to copy an RTCError, as opposed to moving it.
|
||||
// Can revisit this decision if use cases arise in the future.
|
||||
RTCError(const RTCError& other) = delete;
|
||||
RTCError& operator=(const RTCError& other) = delete;
|
||||
|
||||
// Move constructor and move-assignment operator.
|
||||
RTCError(RTCError&& other);
|
||||
RTCError& operator=(RTCError&& other);
|
||||
|
||||
~RTCError();
|
||||
|
||||
// Identical to default constructed error.
|
||||
//
|
||||
// Preferred over the default constructor for code readability.
|
||||
static RTCError OK();
|
||||
|
||||
// Error type.
|
||||
RTCErrorType type() const { return type_; }
|
||||
void set_type(RTCErrorType type) { type_ = type; }
|
||||
|
||||
// Human-readable message describing the error. Shouldn't be used for
|
||||
// anything but logging/diagnostics, since messages are not guaranteed to be
|
||||
// stable.
|
||||
const char* message() const;
|
||||
// For performance, prefer using the method that takes a const char* if the
|
||||
// message is a static string.
|
||||
void set_message(const char* message);
|
||||
void set_message(std::string&& message);
|
||||
|
||||
// Convenience method for situations where you only care whether or not an
|
||||
// error occurred.
|
||||
bool ok() const { return type_ == RTCErrorType::NONE; }
|
||||
|
||||
private:
|
||||
RTCErrorType type_ = RTCErrorType::NONE;
|
||||
// For performance, we use static strings wherever possible. But in some
|
||||
// cases the error string may need to be constructed, in which case an
|
||||
// std::string is used.
|
||||
union {
|
||||
const char* static_message_ = "";
|
||||
std::string string_message_;
|
||||
};
|
||||
// Whether or not |static_message_| or |string_message_| is being used in the
|
||||
// above union.
|
||||
bool have_string_message_ = false;
|
||||
};
|
||||
|
||||
// Outputs the error as a friendly string. Update this method when adding a new
|
||||
// error type.
|
||||
//
|
||||
// Only intended to be used for logging/disagnostics.
|
||||
std::ostream& operator<<(std::ostream& stream, RTCErrorType error);
|
||||
|
||||
// Helper macro that can be used by implementations to create an error with a
|
||||
// message and log it. |message| should be a string literal or movable
|
||||
// std::string.
|
||||
#define LOG_AND_RETURN_ERROR_EX(type, message, severity) \
|
||||
{ \
|
||||
RTC_DCHECK(type != RTCErrorType::NONE); \
|
||||
LOG(severity) << message << " (" << type << ")"; \
|
||||
return webrtc::RTCError(type, message); \
|
||||
}
|
||||
|
||||
#define LOG_AND_RETURN_ERROR(type, message) \
|
||||
LOG_AND_RETURN_ERROR_EX(type, message, LS_ERROR)
|
||||
|
||||
// RTCErrorOr<T> is the union of an RTCError object and a T object. RTCErrorOr
|
||||
// models the concept of an object that is either a usable value, or an error
|
||||
// Status explaining why such a value is not present. To this end RTCErrorOr<T>
|
||||
// does not allow its RTCErrorType value to be RTCErrorType::NONE. This is
|
||||
// enforced by a debug check in most cases.
|
||||
//
|
||||
// The primary use-case for RTCErrorOr<T> is as the return value of a function
|
||||
// which may fail. For example, CreateRtpSender will fail if the parameters
|
||||
// could not be successfully applied at the media engine level, but if
|
||||
// successful will return a unique_ptr to an RtpSender.
|
||||
//
|
||||
// Example client usage for a RTCErrorOr<std::unique_ptr<T>>:
|
||||
//
|
||||
// RTCErrorOr<std::unique_ptr<Foo>> result = FooFactory::MakeNewFoo(arg);
|
||||
// if (result.ok()) {
|
||||
// std::unique_ptr<Foo> foo = result.ConsumeValue();
|
||||
// foo->DoSomethingCool();
|
||||
// } else {
|
||||
// LOG(LS_ERROR) << result.error();
|
||||
// }
|
||||
//
|
||||
// Example factory implementation returning RTCErrorOr<std::unique_ptr<T>>:
|
||||
//
|
||||
// RTCErrorOr<std::unique_ptr<Foo>> FooFactory::MakeNewFoo(int arg) {
|
||||
// if (arg <= 0) {
|
||||
// return RTCError(RTCErrorType::INVALID_RANGE, "Arg must be positive");
|
||||
// } else {
|
||||
// return std::unique_ptr<Foo>(new Foo(arg));
|
||||
// }
|
||||
// }
|
||||
//
|
||||
template <typename T>
|
||||
class RTCErrorOr {
|
||||
// Used to convert between RTCErrorOr<Foo>/RtcErrorOr<Bar>, when an implicit
|
||||
// conversion from Foo to Bar exists.
|
||||
template <typename U>
|
||||
friend class RTCErrorOr;
|
||||
|
||||
public:
|
||||
typedef T element_type;
|
||||
|
||||
// Constructs a new RTCErrorOr with RTCErrorType::INTERNAL_ERROR error. This
|
||||
// is marked 'explicit' to try to catch cases like 'return {};', where people
|
||||
// think RTCErrorOr<std::vector<int>> will be initialized with an empty
|
||||
// vector, instead of a RTCErrorType::INTERNAL_ERROR error.
|
||||
explicit RTCErrorOr() : error_(RTCErrorType::INTERNAL_ERROR) {}
|
||||
|
||||
// Constructs a new RTCErrorOr with the given non-ok error. After calling
|
||||
// this constructor, calls to value() will DCHECK-fail.
|
||||
//
|
||||
// NOTE: Not explicit - we want to use RTCErrorOr<T> as a return
|
||||
// value, so it is convenient and sensible to be able to do 'return
|
||||
// RTCError(...)' when the return type is RTCErrorOr<T>.
|
||||
//
|
||||
// REQUIRES: !error.ok(). This requirement is DCHECKed.
|
||||
RTCErrorOr(RTCError&& error) : error_(std::move(error)) {
|
||||
RTC_DCHECK(!error.ok());
|
||||
}
|
||||
|
||||
// Constructs a new RTCErrorOr with the given value. After calling this
|
||||
// constructor, calls to value() will succeed, and calls to error() will
|
||||
// return a default-constructed RTCError.
|
||||
//
|
||||
// NOTE: Not explicit - we want to use RTCErrorOr<T> as a return type
|
||||
// so it is convenient and sensible to be able to do 'return T()'
|
||||
// when the return type is RTCErrorOr<T>.
|
||||
RTCErrorOr(T value) : value_(std::move(value)) {}
|
||||
|
||||
// Delete the copy constructor and assignment operator; there aren't any use
|
||||
// cases where you should need to copy an RTCErrorOr, as opposed to moving
|
||||
// it. Can revisit this decision if use cases arise in the future.
|
||||
RTCErrorOr(const RTCErrorOr& other) = delete;
|
||||
RTCErrorOr& operator=(const RTCErrorOr& other) = delete;
|
||||
|
||||
// Move constructor and move-assignment operator.
|
||||
RTCErrorOr(RTCErrorOr&& other) = default;
|
||||
RTCErrorOr& operator=(RTCErrorOr&& other) = default;
|
||||
|
||||
// Conversion constructor and assignment operator; T must be copy or move
|
||||
// constructible from U.
|
||||
template <typename U>
|
||||
RTCErrorOr(RTCErrorOr<U> other)
|
||||
: error_(std::move(other.error_)), value_(std::move(other.value_)) {}
|
||||
template <typename U>
|
||||
RTCErrorOr& operator=(RTCErrorOr<U> other) {
|
||||
error_ = std::move(other.error_);
|
||||
value_ = std::move(other.value_);
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Returns a reference to our error. If this contains a T, then returns
|
||||
// default-constructed RTCError.
|
||||
const RTCError& error() const { return error_; }
|
||||
|
||||
// Moves the error. Can be useful if, say "CreateFoo" returns an
|
||||
// RTCErrorOr<Foo>, and internally calls "CreateBar" which returns an
|
||||
// RTCErrorOr<Bar>, and wants to forward the error up the stack.
|
||||
RTCError MoveError() { return std::move(error_); }
|
||||
|
||||
// Returns this->error().ok()
|
||||
bool ok() const { return error_.ok(); }
|
||||
|
||||
// Returns a reference to our current value, or DCHECK-fails if !this->ok().
|
||||
//
|
||||
// Can be convenient for the implementation; for example, a method may want
|
||||
// to access the value in some way before returning it to the next method on
|
||||
// the stack.
|
||||
const T& value() const {
|
||||
RTC_DCHECK(ok());
|
||||
return value_;
|
||||
}
|
||||
T& value() {
|
||||
RTC_DCHECK(ok());
|
||||
return value_;
|
||||
}
|
||||
|
||||
// Moves our current value out of this object and returns it, or DCHECK-fails
|
||||
// if !this->ok().
|
||||
T MoveValue() {
|
||||
RTC_DCHECK(ok());
|
||||
return std::move(value_);
|
||||
}
|
||||
|
||||
private:
|
||||
RTCError error_;
|
||||
T value_;
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // WEBRTC_API_RTCERROR_H_
|
||||
241
webrtc/api/rtcerror_unittest.cc
Normal file
241
webrtc/api/rtcerror_unittest.cc
Normal file
@ -0,0 +1,241 @@
|
||||
/*
|
||||
* Copyright 2017 The WebRTC Project Authors. All rights reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include <utility>
|
||||
|
||||
#include "webrtc/api/rtcerror.h"
|
||||
#include "webrtc/test/gtest.h"
|
||||
|
||||
namespace {
|
||||
|
||||
const int kDefaultMoveOnlyIntValue = 0xbadf00d;
|
||||
|
||||
// Class that has no copy constructor, ensuring that RTCErrorOr can
|
||||
struct MoveOnlyInt {
|
||||
MoveOnlyInt() {}
|
||||
explicit MoveOnlyInt(int value) : value(value) {}
|
||||
MoveOnlyInt(const MoveOnlyInt& other) = delete;
|
||||
MoveOnlyInt(MoveOnlyInt&& other) = default;
|
||||
MoveOnlyInt& operator=(MoveOnlyInt&& other) = default;
|
||||
|
||||
int value = kDefaultMoveOnlyIntValue;
|
||||
};
|
||||
|
||||
// Same as above. Used to test conversion from RTCErrorOr<A> to RTCErrorOr<B>
|
||||
// when A can be converted to B.
|
||||
struct MoveOnlyInt2 {
|
||||
MoveOnlyInt2() {}
|
||||
explicit MoveOnlyInt2(int value) : value(value) {}
|
||||
MoveOnlyInt2(const MoveOnlyInt2& other) = delete;
|
||||
MoveOnlyInt2(MoveOnlyInt2&& other) = default;
|
||||
MoveOnlyInt2& operator=(MoveOnlyInt2&& other) = default;
|
||||
|
||||
explicit MoveOnlyInt2(MoveOnlyInt&& other) : value(other.value) {}
|
||||
MoveOnlyInt2& operator=(MoveOnlyInt&& other) {
|
||||
value = other.value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
int value = kDefaultMoveOnlyIntValue;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
// Simple test for ostream operator for RTCErrorType.
|
||||
TEST(RTCErrorTypeTest, OstreamOperator) {
|
||||
std::ostringstream oss;
|
||||
oss << webrtc::RTCErrorType::NONE << ' '
|
||||
<< webrtc::RTCErrorType::INVALID_PARAMETER << ' '
|
||||
<< webrtc::RTCErrorType::INTERNAL_ERROR;
|
||||
EXPECT_EQ("NONE INVALID_PARAMETER INTERNAL_ERROR", oss.str());
|
||||
}
|
||||
|
||||
// Test that the default constructor creates a "no error" error.
|
||||
TEST(RTCErrorTest, DefaultConstructor) {
|
||||
RTCError e;
|
||||
EXPECT_EQ(RTCErrorType::NONE, e.type());
|
||||
EXPECT_EQ(std::string(), e.message());
|
||||
EXPECT_TRUE(e.ok());
|
||||
}
|
||||
|
||||
TEST(RTCErrorTest, NormalConstructors) {
|
||||
RTCError a(RTCErrorType::INVALID_PARAMETER);
|
||||
EXPECT_EQ(RTCErrorType::INVALID_PARAMETER, a.type());
|
||||
EXPECT_EQ(std::string(), a.message());
|
||||
|
||||
// Constructor that takes const char* message.
|
||||
RTCError b(RTCErrorType::UNSUPPORTED_PARAMETER, "foobar");
|
||||
EXPECT_EQ(RTCErrorType::UNSUPPORTED_PARAMETER, b.type());
|
||||
EXPECT_EQ(std::string("foobar"), b.message());
|
||||
|
||||
// Constructor that takes std::string message.
|
||||
RTCError c(RTCErrorType::INVALID_RANGE, std::string("new"));
|
||||
EXPECT_EQ(RTCErrorType::INVALID_RANGE, c.type());
|
||||
EXPECT_EQ(std::string("new"), c.message());
|
||||
}
|
||||
|
||||
TEST(RTCErrorTest, MoveConstructor) {
|
||||
// Static string.
|
||||
RTCError a(RTCErrorType::INVALID_PARAMETER, "foo");
|
||||
RTCError b(std::move(a));
|
||||
EXPECT_EQ(RTCErrorType::INVALID_PARAMETER, b.type());
|
||||
EXPECT_EQ(std::string("foo"), b.message());
|
||||
|
||||
// Non-static string.
|
||||
RTCError c(RTCErrorType::UNSUPPORTED_PARAMETER, std::string("bar"));
|
||||
RTCError d(std::move(c));
|
||||
EXPECT_EQ(RTCErrorType::UNSUPPORTED_PARAMETER, d.type());
|
||||
EXPECT_EQ(std::string("bar"), d.message());
|
||||
}
|
||||
|
||||
TEST(RTCErrorTest, MoveAssignment) {
|
||||
// Try all combinations of "is static string"/"is non-static string" moves.
|
||||
RTCError e(RTCErrorType::INVALID_PARAMETER, "foo");
|
||||
|
||||
e = RTCError(RTCErrorType::UNSUPPORTED_PARAMETER, "bar");
|
||||
EXPECT_EQ(RTCErrorType::UNSUPPORTED_PARAMETER, e.type());
|
||||
EXPECT_EQ(std::string("bar"), e.message());
|
||||
|
||||
e = RTCError(RTCErrorType::SYNTAX_ERROR, std::string("baz"));
|
||||
EXPECT_EQ(std::string("baz"), e.message());
|
||||
|
||||
e = RTCError(RTCErrorType::SYNTAX_ERROR, std::string("another"));
|
||||
EXPECT_EQ(std::string("another"), e.message());
|
||||
|
||||
e = RTCError(RTCErrorType::SYNTAX_ERROR, "last");
|
||||
EXPECT_EQ(std::string("last"), e.message());
|
||||
}
|
||||
|
||||
// Test that the error returned by RTCError::OK() is a "no error" error.
|
||||
TEST(RTCErrorTest, OKConstant) {
|
||||
RTCError ok = RTCError::OK();
|
||||
EXPECT_EQ(RTCErrorType::NONE, ok.type());
|
||||
EXPECT_EQ(std::string(), ok.message());
|
||||
EXPECT_TRUE(ok.ok());
|
||||
}
|
||||
|
||||
// Test that "error.ok()" behaves as expected.
|
||||
TEST(RTCErrorTest, OkMethod) {
|
||||
RTCError success;
|
||||
RTCError failure(RTCErrorType::INTERNAL_ERROR);
|
||||
EXPECT_TRUE(success.ok());
|
||||
EXPECT_FALSE(failure.ok());
|
||||
}
|
||||
|
||||
// Test that a message can be set using either static const strings or
|
||||
// std::strings.
|
||||
TEST(RTCErrorTest, SetMessage) {
|
||||
RTCError e;
|
||||
// Try all combinations of "is static string"/"is non-static string" calls.
|
||||
e.set_message("foo");
|
||||
EXPECT_EQ(std::string("foo"), e.message());
|
||||
|
||||
e.set_message("bar");
|
||||
EXPECT_EQ(std::string("bar"), e.message());
|
||||
|
||||
e.set_message(std::string("string"));
|
||||
EXPECT_EQ(std::string("string"), e.message());
|
||||
|
||||
e.set_message(std::string("more"));
|
||||
EXPECT_EQ(std::string("more"), e.message());
|
||||
|
||||
e.set_message("love to test");
|
||||
EXPECT_EQ(std::string("love to test"), e.message());
|
||||
}
|
||||
|
||||
// Test that the default constructor creates an "INTERNAL_ERROR".
|
||||
TEST(RTCErrorOrTest, DefaultConstructor) {
|
||||
RTCErrorOr<MoveOnlyInt> e;
|
||||
EXPECT_EQ(RTCErrorType::INTERNAL_ERROR, e.error().type());
|
||||
}
|
||||
|
||||
// Test that an RTCErrorOr can be implicitly constructed from a value.
|
||||
TEST(RTCErrorOrTest, ImplicitValueConstructor) {
|
||||
RTCErrorOr<MoveOnlyInt> e = [] { return MoveOnlyInt(100); }();
|
||||
EXPECT_EQ(100, e.value().value);
|
||||
}
|
||||
|
||||
// Test that an RTCErrorOr can be implicitly constructed from an RTCError.
|
||||
TEST(RTCErrorOrTest, ImplicitErrorConstructor) {
|
||||
RTCErrorOr<MoveOnlyInt> e = [] {
|
||||
return RTCError(RTCErrorType::SYNTAX_ERROR);
|
||||
}();
|
||||
EXPECT_EQ(RTCErrorType::SYNTAX_ERROR, e.error().type());
|
||||
}
|
||||
|
||||
TEST(RTCErrorOrTest, MoveConstructor) {
|
||||
RTCErrorOr<MoveOnlyInt> a(MoveOnlyInt(5));
|
||||
RTCErrorOr<MoveOnlyInt> b(std::move(a));
|
||||
EXPECT_EQ(5, b.value().value);
|
||||
}
|
||||
|
||||
TEST(RTCErrorOrTest, MoveAssignment) {
|
||||
RTCErrorOr<MoveOnlyInt> a(MoveOnlyInt(5));
|
||||
RTCErrorOr<MoveOnlyInt> b(MoveOnlyInt(10));
|
||||
a = std::move(b);
|
||||
EXPECT_EQ(10, a.value().value);
|
||||
}
|
||||
|
||||
TEST(RTCErrorOrTest, ConversionConstructor) {
|
||||
RTCErrorOr<MoveOnlyInt> a(MoveOnlyInt(1));
|
||||
RTCErrorOr<MoveOnlyInt2> b(std::move(a));
|
||||
}
|
||||
|
||||
TEST(RTCErrorOrTest, ConversionAssignment) {
|
||||
RTCErrorOr<MoveOnlyInt> a(MoveOnlyInt(5));
|
||||
RTCErrorOr<MoveOnlyInt2> b(MoveOnlyInt2(10));
|
||||
b = std::move(a);
|
||||
EXPECT_EQ(5, b.value().value);
|
||||
}
|
||||
|
||||
TEST(RTCErrorOrTest, OkMethod) {
|
||||
RTCErrorOr<int> success(1337);
|
||||
RTCErrorOr<int> error = RTCError(RTCErrorType::INTERNAL_ERROR);
|
||||
EXPECT_TRUE(success.ok());
|
||||
EXPECT_FALSE(error.ok());
|
||||
}
|
||||
|
||||
TEST(RTCErrorOrTest, MoveError) {
|
||||
RTCErrorOr<int> e({RTCErrorType::SYNTAX_ERROR, "message"});
|
||||
RTCError err = e.MoveError();
|
||||
EXPECT_EQ(RTCErrorType::SYNTAX_ERROR, err.type());
|
||||
EXPECT_EQ(std::string("message"), err.message());
|
||||
}
|
||||
|
||||
TEST(RTCErrorOrTest, MoveValue) {
|
||||
RTCErrorOr<MoveOnlyInt> e(MoveOnlyInt(88));
|
||||
MoveOnlyInt value = e.MoveValue();
|
||||
EXPECT_EQ(88, value.value);
|
||||
}
|
||||
|
||||
// Death tests.
|
||||
// Disabled on Android because death tests misbehave on Android, see
|
||||
// base/test/gtest_util.h.
|
||||
#if RTC_DCHECK_IS_ON && GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID)
|
||||
|
||||
TEST(RTCErrorOrDeathTest, ConstructWithOkError) {
|
||||
EXPECT_DEATH(RTCErrorOr<int> err = RTCError::OK(), "");
|
||||
}
|
||||
|
||||
TEST(RTCErrorOrDeathTest, DereferenceErrorValue) {
|
||||
RTCErrorOr<int> error = RTCError(RTCErrorType::INTERNAL_ERROR);
|
||||
EXPECT_DEATH(error.value(), "");
|
||||
}
|
||||
|
||||
TEST(RTCErrorOrDeathTest, MoveErrorValue) {
|
||||
RTCErrorOr<int> error = RTCError(RTCErrorType::INTERNAL_ERROR);
|
||||
EXPECT_DEATH(error.MoveValue(), "");
|
||||
}
|
||||
|
||||
#endif // RTC_DCHECK_IS_ON && GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID)
|
||||
|
||||
} // namespace webrtc
|
||||
@ -458,27 +458,6 @@ bool SafeSetError(webrtc::RTCErrorType type, webrtc::RTCError* error) {
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
static const char* const kRTCErrorTypeNames[] = {
|
||||
"NONE",
|
||||
"UNSUPPORTED_PARAMETER",
|
||||
"INVALID_PARAMETER",
|
||||
"INVALID_RANGE",
|
||||
"SYNTAX_ERROR",
|
||||
"INVALID_STATE",
|
||||
"INVALID_MODIFICATION",
|
||||
"NETWORK_ERROR",
|
||||
"INTERNAL_ERROR",
|
||||
};
|
||||
static_assert(static_cast<int>(RTCErrorType::INTERNAL_ERROR) ==
|
||||
(arraysize(kRTCErrorTypeNames) - 1),
|
||||
"kRTCErrorTypeNames must have as many strings as RTCErrorType "
|
||||
"has values.");
|
||||
|
||||
std::ostream& operator<<(std::ostream& stream, RTCErrorType error) {
|
||||
int index = static_cast<int>(error);
|
||||
return stream << kRTCErrorTypeNames[index];
|
||||
}
|
||||
|
||||
bool PeerConnectionInterface::RTCConfiguration::operator==(
|
||||
const PeerConnectionInterface::RTCConfiguration& o) const {
|
||||
// This static_assert prevents us from accidentally breaking operator==.
|
||||
|
||||
@ -3384,14 +3384,6 @@ TEST(CreateSessionOptionsTest, MediaConstraintsInAnswer) {
|
||||
EXPECT_TRUE(updated_answer_options.has_video());
|
||||
}
|
||||
|
||||
TEST(RTCErrorTypeTest, OstreamOperator) {
|
||||
std::ostringstream oss;
|
||||
oss << webrtc::RTCErrorType::NONE << ' '
|
||||
<< webrtc::RTCErrorType::INVALID_PARAMETER << ' '
|
||||
<< webrtc::RTCErrorType::INTERNAL_ERROR;
|
||||
EXPECT_EQ("NONE INVALID_PARAMETER INTERNAL_ERROR", oss.str());
|
||||
}
|
||||
|
||||
// Tests a few random fields being different.
|
||||
TEST(RTCConfigurationTest, ComparisonOperators) {
|
||||
PeerConnectionInterface::RTCConfiguration a;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user