-
Notifications
You must be signed in to change notification settings - Fork 13
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Issue 29, check for bad client version #40
base: master
Are you sure you want to change the base?
Changes from all commits
c80c919
3e434a6
6f8cc4d
3c37592
09cb638
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -67,6 +67,15 @@ bool Absorber::HandleNewMessage(net::ConnectionPtr connection, | |
|
||
if (message->HasExtension(proto::Remote::extension)) { | ||
Message execute(message->ReleaseExtension(proto::Remote::extension)); | ||
auto config = conf(); | ||
if (execute->emitter_version() < config->absorber().min_emitter_version()) { | ||
LOG(WARNING) << "Emitter sent a bad version: " | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Better not to mention |
||
<< execute->emitter_version(); | ||
net::proto::Status bad_version_status; | ||
bad_version_status.set_code(net::proto::Status::BAD_EMITTER_VERSION); | ||
return connection->ReportStatus(bad_version_status); | ||
} | ||
|
||
DCHECK(!execute->flags().compiler().has_path()); | ||
if (execute->has_source()) { | ||
return tasks_->Push(Task{connection, std::move(execute)}); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -8,15 +8,24 @@ namespace daemon { | |
|
||
namespace { | ||
|
||
static const ui32 kEmptyEmitterVersion = 0u; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. no need for |
||
static const ui32 kBadEmitterVersion = 1u; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Anyway, it's better not to use a module-wide constants outside of test bodies - just for couple of them. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This constant should be replaced with something like |
||
static const ui32 kGoodEmitterVersion = 100u; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This constant should be replaced with something like |
||
|
||
// S1..4 types can be one of the following: |String|, |Immutable|, |Literal| | ||
template <typename S1, typename S2, typename S3, typename S4 = String> | ||
net::Connection::ScopedMessage CreateMessage(const S1& source, | ||
const S2& action, | ||
const S3& compiler_version, | ||
const S4& language = S4()) { | ||
net::Connection::ScopedMessage CreateMessage( | ||
const S1& source, | ||
const S2& action, | ||
const S3& compiler_version, | ||
const S4& language = S4(), | ||
ui32 emitter_version = kEmptyEmitterVersion) { | ||
net::Connection::ScopedMessage message(new net::Connection::Message); | ||
auto* extension = message->MutableExtension(proto::Remote::extension); | ||
extension->set_source(source); | ||
if (emitter_version != kEmptyEmitterVersion) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Forgot braces |
||
extension->set_emitter_version(emitter_version); | ||
|
||
auto* compiler = extension->mutable_flags()->mutable_compiler(); | ||
compiler->set_version(compiler_version); | ||
extension->mutable_flags()->set_action(action); | ||
|
@@ -374,5 +383,148 @@ TEST_F(AbsorberTest, BadMessageStatus) { | |
<< "Daemon must not store references to the connection"; | ||
} | ||
|
||
TEST_F(AbsorberTest, BadEmitterVersion) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Better not to mention "Emitter". |
||
const String expected_host = "fake_host"; | ||
const ui16 expected_port = 12345; | ||
const String compiler_version("compiler_version"); | ||
const String compiler_path("compiler_path"); | ||
|
||
conf.mutable_absorber()->mutable_local()->set_host(expected_host); | ||
conf.mutable_absorber()->mutable_local()->set_port(expected_port); | ||
conf.mutable_absorber()->set_min_emitter_version(kGoodEmitterVersion); | ||
auto* version = conf.add_versions(); | ||
version->set_version(compiler_version); | ||
version->set_path(compiler_path); | ||
|
||
listen_callback = | ||
[&expected_host, expected_port](const String& host, ui16 port, String*) { | ||
EXPECT_EQ(expected_host, host); | ||
EXPECT_EQ(expected_port, port); | ||
return true; | ||
}; | ||
connect_callback = [](net::TestConnection* connection) { | ||
connection->CallOnSend([](const net::Connection::Message& message) { | ||
EXPECT_TRUE(message.HasExtension(net::proto::Status::extension)); | ||
const auto& status = message.GetExtension(net::proto::Status::extension); | ||
EXPECT_EQ(net::proto::Status::BAD_EMITTER_VERSION, status.code()); | ||
|
||
EXPECT_FALSE(message.HasExtension(proto::Result::extension)); | ||
}); | ||
}; | ||
|
||
absorber.reset(new Absorber(conf)); | ||
ASSERT_TRUE(absorber->Initialize()); | ||
|
||
auto connection1 = test_service->TriggerListen(expected_host, expected_port); | ||
{ | ||
SharedPtr<net::TestConnection> test_connection = | ||
std::static_pointer_cast<net::TestConnection>(connection1); | ||
|
||
auto message(CreateMessage(""_l, ""_l, ""_l, ""_l, kBadEmitterVersion)); | ||
EXPECT_TRUE( | ||
test_connection->TriggerReadAsync(std::move(message), StatusOK())); | ||
|
||
UniqueLock lock(send_mutex); | ||
ASSERT_TRUE(send_condition.wait_for(lock, std::chrono::seconds(1), | ||
[this] { return send_count == 1; })); | ||
} | ||
|
||
auto connection2 = test_service->TriggerListen(expected_host, expected_port); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This part doesn't correspond to the test's purpose - according to its name. It's better to leave only the first connection. |
||
{ | ||
SharedPtr<net::TestConnection> test_connection = | ||
std::static_pointer_cast<net::TestConnection>(connection2); | ||
|
||
test_connection->CallOnSend([](const net::Connection::Message& message) { | ||
EXPECT_TRUE(message.HasExtension(net::proto::Status::extension)); | ||
const auto& status = message.GetExtension(net::proto::Status::extension); | ||
EXPECT_EQ(net::proto::Status::OK, status.code()); | ||
|
||
EXPECT_TRUE(message.HasExtension(proto::Result::extension)); | ||
EXPECT_TRUE(message.GetExtension(proto::Result::extension).has_obj()); | ||
}); | ||
auto message(CreateMessage("source"_l, "action"_l, compiler_version)); | ||
auto* extension = message->MutableExtension(proto::Remote::extension); | ||
|
||
// Force to use default value from .proto file | ||
extension->clear_emitter_version(); | ||
EXPECT_TRUE( | ||
test_connection->TriggerReadAsync(std::move(message), StatusOK())); | ||
|
||
UniqueLock lock(send_mutex); | ||
ASSERT_TRUE(send_condition.wait_for(lock, std::chrono::seconds(1), | ||
[this] { return send_count == 2; })); | ||
} | ||
|
||
absorber.reset(); | ||
|
||
EXPECT_EQ(1u, run_count); | ||
EXPECT_EQ(1u, listen_count); | ||
EXPECT_EQ(2u, connect_count); | ||
EXPECT_EQ(2u, connections_created); | ||
EXPECT_EQ(2u, read_count); | ||
EXPECT_EQ(2u, send_count); | ||
EXPECT_EQ(1, connection1.use_count()) | ||
<< "Daemon must not store references to the connection"; | ||
EXPECT_EQ(1, connection2.use_count()) | ||
<< "Daemon must not store references to the connection"; | ||
} | ||
|
||
TEST_F(AbsorberTest, GoodCustomEmitterVersion) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think, you should modify the existing |
||
const String expected_host = "fake_host"; | ||
const ui16 expected_port = 12345; | ||
const String compiler_version("compiler_version"); | ||
const String compiler_path("compiler_path"); | ||
const ui32 custom_emitter_version = kGoodEmitterVersion + 1000; | ||
|
||
conf.mutable_absorber()->mutable_local()->set_host(expected_host); | ||
conf.mutable_absorber()->mutable_local()->set_port(expected_port); | ||
conf.mutable_absorber()->set_min_emitter_version(custom_emitter_version); | ||
auto* version = conf.add_versions(); | ||
version->set_version(compiler_version); | ||
version->set_path(compiler_path); | ||
|
||
listen_callback = | ||
[&expected_host, expected_port](const String& host, ui16 port, String*) { | ||
EXPECT_EQ(expected_host, host); | ||
EXPECT_EQ(expected_port, port); | ||
return true; | ||
}; | ||
connect_callback = [](net::TestConnection* connection) { | ||
connection->CallOnSend([](const net::Connection::Message& message) { | ||
EXPECT_TRUE(message.HasExtension(net::proto::Status::extension)); | ||
const auto& status = message.GetExtension(net::proto::Status::extension); | ||
EXPECT_EQ(net::proto::Status::OK, status.code()); | ||
|
||
EXPECT_TRUE(message.HasExtension(proto::Result::extension)); | ||
EXPECT_TRUE(message.GetExtension(proto::Result::extension).has_obj()); | ||
}); | ||
}; | ||
|
||
absorber.reset(new Absorber(conf)); | ||
ASSERT_TRUE(absorber->Initialize()); | ||
|
||
auto connection = test_service->TriggerListen(expected_host, expected_port); | ||
{ | ||
SharedPtr<net::TestConnection> test_connection = | ||
std::static_pointer_cast<net::TestConnection>(connection); | ||
|
||
auto message(CreateMessage("source"_l, "action"_l, compiler_version, ""_l, | ||
custom_emitter_version)); | ||
EXPECT_TRUE( | ||
test_connection->TriggerReadAsync(std::move(message), StatusOK())); | ||
|
||
absorber.reset(); | ||
} | ||
|
||
EXPECT_EQ(1u, run_count); | ||
EXPECT_EQ(1u, listen_count); | ||
EXPECT_EQ(1u, connect_count); | ||
EXPECT_EQ(1u, connections_created); | ||
EXPECT_EQ(1u, read_count); | ||
EXPECT_EQ(1u, send_count); | ||
EXPECT_EQ(1, connection.use_count()) | ||
<< "Daemon must not store references to the connection"; | ||
} | ||
|
||
} // namespace daemon | ||
} // namespace dist_clang |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -57,7 +57,8 @@ message Configuration { | |
} | ||
|
||
message Absorber { | ||
required Host local = 1; | ||
required Host local = 1; | ||
optional uint32 min_emitter_version = 2 [ default = 100 ]; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Use shared message type of |
||
} | ||
|
||
message Collector { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -7,6 +7,7 @@ package dist_clang.daemon.proto; | |
message Remote { | ||
optional base.proto.Flags flags = 1; | ||
optional string source = 2; | ||
optional uint32 emitter_version = 3 [ default = 100 ]; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Let it be simply "version" - and the default value should be real, i.e. the current version (790.0). Also the real version is complex and consists of two numbers: better to reflect it as a separate message type, like:
This message type should be shared with a its counterpart in Absorber message. |
||
|
||
extend net.proto.Universal { | ||
optional Remote extension = 6; | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -9,14 +9,15 @@ message Universal { | |
|
||
message Status { | ||
enum Code { | ||
OK = 0; | ||
INCONSEQUENT = 1; | ||
NETWORK = 2; | ||
BAD_MESSAGE = 3; | ||
EMPTY_MESSAGE = 4; | ||
EXECUTION = 5; | ||
OVERLOAD = 6; | ||
NO_VERSION = 7; | ||
OK = 0; | ||
INCONSEQUENT = 1; | ||
NETWORK = 2; | ||
BAD_MESSAGE = 3; | ||
EMPTY_MESSAGE = 4; | ||
EXECUTION = 5; | ||
OVERLOAD = 6; | ||
NO_VERSION = 7; | ||
BAD_EMITTER_VERSION = 8; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Better to choose one or two words, like |
||
} | ||
|
||
required Code code = 1 [ default = OK ]; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Implement comparison for the complex version.