1 // Copyright (c) 2015-2016 The Khronos Group Inc.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include <algorithm>
16 #include <sstream>
17 #include <utility>
18
19 #include "gmock/gmock.h"
20 #include "test/unit_spirv.h"
21
22 namespace spvtools {
23 namespace {
24
25 using ::testing::Eq;
26
27 // Returns a newly created diagnostic value.
MakeValidDiagnostic()28 spv_diagnostic MakeValidDiagnostic() {
29 spv_position_t position = {};
30 spv_diagnostic diagnostic = spvDiagnosticCreate(&position, "");
31 EXPECT_NE(nullptr, diagnostic);
32 return diagnostic;
33 }
34
TEST(Diagnostic,DestroyNull)35 TEST(Diagnostic, DestroyNull) { spvDiagnosticDestroy(nullptr); }
36
TEST(Diagnostic,DestroyValidDiagnostic)37 TEST(Diagnostic, DestroyValidDiagnostic) {
38 spv_diagnostic diagnostic = MakeValidDiagnostic();
39 spvDiagnosticDestroy(diagnostic);
40 // We aren't allowed to use the diagnostic pointer anymore.
41 // So we can't test its behaviour.
42 }
43
TEST(Diagnostic,DestroyValidDiagnosticAfterReassignment)44 TEST(Diagnostic, DestroyValidDiagnosticAfterReassignment) {
45 spv_diagnostic diagnostic = MakeValidDiagnostic();
46 spv_diagnostic second_diagnostic = MakeValidDiagnostic();
47 EXPECT_TRUE(diagnostic != second_diagnostic);
48 spvDiagnosticDestroy(diagnostic);
49 diagnostic = second_diagnostic;
50 spvDiagnosticDestroy(diagnostic);
51 }
52
TEST(Diagnostic,PrintDefault)53 TEST(Diagnostic, PrintDefault) {
54 char message[] = "Test Diagnostic!";
55 spv_diagnostic_t diagnostic = {{2, 3, 5}, message};
56 // TODO: Redirect stderr
57 ASSERT_EQ(SPV_SUCCESS, spvDiagnosticPrint(&diagnostic));
58 // TODO: Validate the output of spvDiagnosticPrint()
59 // TODO: Remove the redirection of stderr
60 }
61
TEST(Diagnostic,PrintInvalidDiagnostic)62 TEST(Diagnostic, PrintInvalidDiagnostic) {
63 ASSERT_EQ(SPV_ERROR_INVALID_DIAGNOSTIC, spvDiagnosticPrint(nullptr));
64 }
65
66 // TODO(dneto): We should be able to redirect the diagnostic printing.
67 // Once we do that, we can test diagnostic corner cases.
68
TEST(DiagnosticStream,ConversionToResultType)69 TEST(DiagnosticStream, ConversionToResultType) {
70 // Check after the DiagnosticStream object is destroyed.
71 spv_result_t value;
72 { value = DiagnosticStream({}, nullptr, "", SPV_ERROR_INVALID_TEXT); }
73 EXPECT_EQ(SPV_ERROR_INVALID_TEXT, value);
74
75 // Check implicit conversion via plain assignment.
76 value = DiagnosticStream({}, nullptr, "", SPV_SUCCESS);
77 EXPECT_EQ(SPV_SUCCESS, value);
78
79 // Check conversion via constructor.
80 EXPECT_EQ(SPV_FAILED_MATCH,
81 spv_result_t(DiagnosticStream({}, nullptr, "", SPV_FAILED_MATCH)));
82 }
83
TEST(DiagnosticStream,MoveConstructorPreservesPreviousMessagesAndPreventsOutputFromExpiringValue)84 TEST(
85 DiagnosticStream,
86 MoveConstructorPreservesPreviousMessagesAndPreventsOutputFromExpiringValue) {
87 std::ostringstream messages;
88 int message_count = 0;
89 auto consumer = [&messages, &message_count](spv_message_level_t, const char*,
90 const spv_position_t&,
91 const char* msg) {
92 message_count++;
93 messages << msg;
94 };
95
96 // Enclose the DiagnosticStream variables in a scope to force destruction.
97 {
98 DiagnosticStream ds0({}, consumer, "", SPV_ERROR_INVALID_BINARY);
99 ds0 << "First";
100 DiagnosticStream ds1(std::move(ds0));
101 ds1 << "Second";
102 }
103 EXPECT_THAT(message_count, Eq(1));
104 EXPECT_THAT(messages.str(), Eq("FirstSecond"));
105 }
106
TEST(DiagnosticStream,MoveConstructorCanBeDirectlyShiftedTo)107 TEST(DiagnosticStream, MoveConstructorCanBeDirectlyShiftedTo) {
108 std::ostringstream messages;
109 int message_count = 0;
110 auto consumer = [&messages, &message_count](spv_message_level_t, const char*,
111 const spv_position_t&,
112 const char* msg) {
113 message_count++;
114 messages << msg;
115 };
116
117 // Enclose the DiagnosticStream variables in a scope to force destruction.
118 {
119 DiagnosticStream ds0({}, consumer, "", SPV_ERROR_INVALID_BINARY);
120 ds0 << "First";
121 std::move(ds0) << "Second";
122 }
123 EXPECT_THAT(message_count, Eq(1));
124 EXPECT_THAT(messages.str(), Eq("FirstSecond"));
125 }
126
TEST(DiagnosticStream,DiagnosticFromLambdaReturnCanStillBeUsed)127 TEST(DiagnosticStream, DiagnosticFromLambdaReturnCanStillBeUsed) {
128 std::ostringstream messages;
129 int message_count = 0;
130 auto consumer = [&messages, &message_count](spv_message_level_t, const char*,
131 const spv_position_t&,
132 const char* msg) {
133 message_count++;
134 messages << msg;
135 };
136
137 {
138 auto emitter = [&consumer]() -> DiagnosticStream {
139 DiagnosticStream ds0({}, consumer, "", SPV_ERROR_INVALID_BINARY);
140 ds0 << "First";
141 return ds0;
142 };
143 emitter() << "Second";
144 }
145 EXPECT_THAT(message_count, Eq(1));
146 EXPECT_THAT(messages.str(), Eq("FirstSecond"));
147 }
148
149 } // namespace
150 } // namespace spvtools
151