// Copyright (c) 2015-2016 The Khronos Group Inc. // // 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 <algorithm> #include <sstream> #include <utility> #include "gmock/gmock.h" #include "test/unit_spirv.h" namespace spvtools { namespace { using ::testing::Eq; // Returns a newly created diagnostic value. spv_diagnostic MakeValidDiagnostic() { spv_position_t position = {}; spv_diagnostic diagnostic = spvDiagnosticCreate(&position, ""); EXPECT_NE(nullptr, diagnostic); return diagnostic; } TEST(Diagnostic, DestroyNull) { spvDiagnosticDestroy(nullptr); } TEST(Diagnostic, DestroyValidDiagnostic) { spv_diagnostic diagnostic = MakeValidDiagnostic(); spvDiagnosticDestroy(diagnostic); // We aren't allowed to use the diagnostic pointer anymore. // So we can't test its behaviour. } TEST(Diagnostic, DestroyValidDiagnosticAfterReassignment) { spv_diagnostic diagnostic = MakeValidDiagnostic(); spv_diagnostic second_diagnostic = MakeValidDiagnostic(); EXPECT_TRUE(diagnostic != second_diagnostic); spvDiagnosticDestroy(diagnostic); diagnostic = second_diagnostic; spvDiagnosticDestroy(diagnostic); } TEST(Diagnostic, PrintDefault) { char message[] = "Test Diagnostic!"; spv_diagnostic_t diagnostic = {{2, 3, 5}, message}; // TODO: Redirect stderr ASSERT_EQ(SPV_SUCCESS, spvDiagnosticPrint(&diagnostic)); // TODO: Validate the output of spvDiagnosticPrint() // TODO: Remove the redirection of stderr } TEST(Diagnostic, PrintInvalidDiagnostic) { ASSERT_EQ(SPV_ERROR_INVALID_DIAGNOSTIC, spvDiagnosticPrint(nullptr)); } // TODO(dneto): We should be able to redirect the diagnostic printing. // Once we do that, we can test diagnostic corner cases. TEST(DiagnosticStream, ConversionToResultType) { // Check after the DiagnosticStream object is destroyed. spv_result_t value; { value = DiagnosticStream({}, nullptr, "", SPV_ERROR_INVALID_TEXT); } EXPECT_EQ(SPV_ERROR_INVALID_TEXT, value); // Check implicit conversion via plain assignment. value = DiagnosticStream({}, nullptr, "", SPV_SUCCESS); EXPECT_EQ(SPV_SUCCESS, value); // Check conversion via constructor. EXPECT_EQ(SPV_FAILED_MATCH, spv_result_t(DiagnosticStream({}, nullptr, "", SPV_FAILED_MATCH))); } TEST( DiagnosticStream, MoveConstructorPreservesPreviousMessagesAndPreventsOutputFromExpiringValue) { std::ostringstream messages; int message_count = 0; auto consumer = [&messages, &message_count](spv_message_level_t, const char*, const spv_position_t&, const char* msg) { message_count++; messages << msg; }; // Enclose the DiagnosticStream variables in a scope to force destruction. { DiagnosticStream ds0({}, consumer, "", SPV_ERROR_INVALID_BINARY); ds0 << "First"; DiagnosticStream ds1(std::move(ds0)); ds1 << "Second"; } EXPECT_THAT(message_count, Eq(1)); EXPECT_THAT(messages.str(), Eq("FirstSecond")); } TEST(DiagnosticStream, MoveConstructorCanBeDirectlyShiftedTo) { std::ostringstream messages; int message_count = 0; auto consumer = [&messages, &message_count](spv_message_level_t, const char*, const spv_position_t&, const char* msg) { message_count++; messages << msg; }; // Enclose the DiagnosticStream variables in a scope to force destruction. { DiagnosticStream ds0({}, consumer, "", SPV_ERROR_INVALID_BINARY); ds0 << "First"; std::move(ds0) << "Second"; } EXPECT_THAT(message_count, Eq(1)); EXPECT_THAT(messages.str(), Eq("FirstSecond")); } TEST(DiagnosticStream, DiagnosticFromLambdaReturnCanStillBeUsed) { std::ostringstream messages; int message_count = 0; auto consumer = [&messages, &message_count](spv_message_level_t, const char*, const spv_position_t&, const char* msg) { message_count++; messages << msg; }; { auto emitter = [&consumer]() -> DiagnosticStream { DiagnosticStream ds0({}, consumer, "", SPV_ERROR_INVALID_BINARY); ds0 << "First"; return ds0; }; emitter() << "Second"; } EXPECT_THAT(message_count, Eq(1)); EXPECT_THAT(messages.str(), Eq("FirstSecond")); } } // namespace } // namespace spvtools