1#pragma once
2
3#include <memory>
4#include <sstream>
5#include <iostream>
6#include <Core/Types.h>
7#include <Common/Exception.h>
8#include <Parsers/Lexer.h>
9
10
11namespace DB
12{
13
14namespace ErrorCodes
15{
16 extern const int LOGICAL_ERROR;
17}
18
19
20/// Checks expected server and client error codes in testmode.
21/// To enable it add special comment after the query: "-- { serverError 60 }" or "-- { clientError 20 }".
22class TestHint
23{
24public:
25 TestHint(bool enabled_, const String & query)
26 : enabled(enabled_)
27 {
28 if (!enabled_)
29 return;
30
31 Lexer lexer(query.data(), query.data() + query.size());
32
33 for (Token token = lexer.nextToken(); !token.isEnd(); token = lexer.nextToken())
34 {
35 if (token.type == TokenType::Comment)
36 {
37 String comment(token.begin, token.begin + token.size());
38
39 if (!comment.empty())
40 {
41 size_t pos_start = comment.find('{', 0);
42 if (pos_start != String::npos)
43 {
44 size_t pos_end = comment.find('}', pos_start);
45 if (pos_end != String::npos)
46 {
47 String hint(comment.begin() + pos_start + 1, comment.begin() + pos_end);
48 parse(hint);
49 }
50 }
51 }
52 }
53 }
54 }
55
56 /// @returns true if it's possible to continue without reconnect
57 bool checkActual(int & actual_server_error, int & actual_client_error,
58 bool & got_exception, std::unique_ptr<Exception> & last_exception) const
59 {
60 if (!enabled)
61 return true;
62
63 if (allErrorsExpected(actual_server_error, actual_client_error))
64 {
65 got_exception = false;
66 last_exception.reset();
67 actual_server_error = 0;
68 actual_client_error = 0;
69 return false;
70 }
71
72 if (lostExpectedError(actual_server_error, actual_client_error))
73 {
74 std::cerr << "Success when error expected. It expects server error "
75 << server_error << ", client error " << client_error << "." << std::endl;
76 got_exception = true;
77 last_exception = std::make_unique<Exception>("Success when error expected", ErrorCodes::LOGICAL_ERROR); /// return error to OS
78 return false;
79 }
80
81 return true;
82 }
83
84 int serverError() const { return server_error; }
85 int clientError() const { return client_error; }
86
87private:
88 bool enabled = false;
89 int server_error = 0;
90 int client_error = 0;
91
92 void parse(const String & hint)
93 {
94 std::stringstream ss;
95 ss << hint;
96 String item;
97
98 while (!ss.eof())
99 {
100 ss >> item;
101 if (ss.eof())
102 break;
103
104 if (item == "serverError")
105 ss >> server_error;
106 else if (item == "clientError")
107 ss >> client_error;
108 }
109 }
110
111 bool allErrorsExpected(int actual_server_error, int actual_client_error) const
112 {
113 return (server_error || client_error) && (server_error == actual_server_error) && (client_error == actual_client_error);
114 }
115
116 bool lostExpectedError(int actual_server_error, int actual_client_error) const
117 {
118 return (server_error && !actual_server_error) || (client_error && !actual_client_error);
119 }
120};
121
122}
123