Add a FailStream error reporting helper
Bug: tint:3
Change-Id: Ie0bb2365a7dd6b2a5e9d0960593fac7586b02922
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/16640
Reviewed-by: dan sinclair <dsinclair@google.com>
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index a949180..b357bf3 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -312,6 +312,7 @@
if(${TINT_BUILD_SPV_PARSER})
list (APPEND TINT_TEST_SRCS
+ reader/spv/fail_stream_test.cc
reader/spv/parser_test.cc
)
endif()
diff --git a/src/reader/spv/fail_stream.h b/src/reader/spv/fail_stream.h
new file mode 100644
index 0000000..b9c4f37
--- /dev/null
+++ b/src/reader/spv/fail_stream.h
@@ -0,0 +1,74 @@
+// Copyright 2020 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef SRC_READER_SPV_FAIL_STREAM_H_
+#define SRC_READER_SPV_FAIL_STREAM_H_
+
+#include <ostream>
+
+namespace tint {
+namespace reader {
+namespace spv {
+
+/// A FailStream object accumulates values onto a given std::ostream,
+/// and can be used to record failure by writing the false value
+/// to given a pointer-to-bool.
+class FailStream {
+ public:
+ /// Creates a new fail stream
+ /// @param status_ptr where we will write false to indicate failure. Assumed
+ /// to be a valid pointer to bool.
+ /// @param out output stream where a message should be written to explain
+ /// the failure
+ FailStream(bool* status_ptr, std::ostream* out)
+ : status_ptr_(status_ptr), out_(out) {}
+ /// Copy constructor
+ /// @param other the fail stream to clone
+ FailStream(const FailStream& other) = default;
+
+ /// Converts to a boolean status. A true result indicates success,
+ /// and a false result indicates failure.
+ /// @returns status
+ operator bool() const { return *status_ptr_; }
+ /// Returns the current status value. This can be more readable
+ /// the conversion operator.
+ /// @returns status
+ bool status() const { return *status_ptr_; }
+
+ /// Records failure.
+ /// @returns a FailStream
+ FailStream& Fail() {
+ *status_ptr_ = false;
+ return *this;
+ }
+
+ /// Appends the given value to the message output stream.
+ /// @param val the value to write to the output stream.
+ /// @returns this object
+ template <typename T>
+ FailStream& operator<<(const T& val) {
+ *out_ << val;
+ return *this;
+ }
+
+ private:
+ bool* status_ptr_;
+ std::ostream* out_;
+};
+
+} // namespace spv
+} // namespace reader
+} // namespace tint
+
+#endif // SRC_READER_SPV_FAIL_STREAM_H_
diff --git a/src/reader/spv/fail_stream_test.cc b/src/reader/spv/fail_stream_test.cc
new file mode 100644
index 0000000..394dc2c
--- /dev/null
+++ b/src/reader/spv/fail_stream_test.cc
@@ -0,0 +1,76 @@
+// Copyright 2020 The Tint Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "src/reader/spv/fail_stream.h"
+
+#include <memory>
+#include <sstream>
+
+#include "gmock/gmock.h"
+
+namespace tint {
+namespace reader {
+namespace spv {
+namespace {
+
+using ::testing::Eq;
+
+using FailStreamTest = ::testing::Test;
+
+TEST_F(FailStreamTest, ConversionToBoolIsSameAsStatusMethod) {
+ bool flag = true;
+ FailStream fs(&flag, nullptr);
+
+ EXPECT_TRUE(fs.status());
+ EXPECT_TRUE(bool(fs));
+ flag = false;
+ EXPECT_FALSE(fs.status());
+ EXPECT_FALSE(bool(fs));
+ flag = true;
+ EXPECT_TRUE(fs.status());
+ EXPECT_TRUE(bool(fs));
+}
+
+TEST_F(FailStreamTest, FailMethodChangesStatusToFalse) {
+ bool flag = true;
+ FailStream fs(&flag, nullptr);
+ EXPECT_TRUE(flag);
+ EXPECT_TRUE(bool(fs));
+ fs.Fail();
+ EXPECT_FALSE(flag);
+ EXPECT_FALSE(bool(fs));
+}
+
+TEST_F(FailStreamTest, FailMethodReturnsSelf) {
+ bool flag = true;
+ FailStream fs(&flag, nullptr);
+ FailStream& result = fs.Fail();
+ EXPECT_THAT(&result, Eq(&fs));
+}
+
+TEST_F(FailStreamTest, ShiftOperatorAccumulatesValues) {
+ bool flag = true;
+ std::stringstream ss;
+ FailStream fs(&flag, &ss);
+
+ ss << "prefix ";
+ fs << "cat " << 42;
+
+ EXPECT_THAT(ss.str(), Eq("prefix cat 42"));
+}
+
+} // namespace
+} // namespace spv
+} // namespace reader
+} // namespace tint
diff --git a/src/reader/spv/parser_test.cc b/src/reader/spv/parser_test.cc
index c32a20c..717034b 100644
--- a/src/reader/spv/parser_test.cc
+++ b/src/reader/spv/parser_test.cc
@@ -24,6 +24,7 @@
namespace reader {
namespace spv {
+namespace {
using ParserTest = testing::Test;
TEST_F(ParserTest, Uint32VecEmpty) {
@@ -36,6 +37,8 @@
// TODO(dneto): uint32 vec, valid SPIR-V
// TODO(dneto): uint32 vec, invalid SPIR-V
+} // namespace
+
} // namespace spv
} // namespace reader
} // namespace tint