Skip to content
This repository has been archived by the owner on Apr 17, 2019. It is now read-only.

Query Responses Factory #1724

Merged
merged 19 commits into from
Sep 26, 2018
Merged

Query Responses Factory #1724

merged 19 commits into from
Sep 26, 2018

Conversation

Akvinikym
Copy link
Contributor

Description of the Change

This PR adds a factory for query responses and tests, which cover all factory's methods.

Benefits

Factory will be able to substitute builders.

Possible Drawbacks

None

Usage Examples or Tests [optional]

New test target proto_query_response_factory_test was added to check the factory.

Signed-off-by: Akvinikym <[email protected]>
Signed-off-by: Akvinikym <[email protected]>
Signed-off-by: Akvinikym <[email protected]>
Signed-off-by: Akvinikym <[email protected]>
Signed-off-by: Akvinikym <[email protected]>
Signed-off-by: Akvinikym <[email protected]>
Signed-off-by: Akvinikym <[email protected]>
@l4l l4l added needs-review pr awaits review from maintainers query All that relates to the iroha querying labels Sep 17, 2018
l4l
l4l previously requested changes Sep 17, 2018
#ifndef IROHA_PROTO_QUERY_RESPONSE_FACTORY_HPP
#define IROHA_PROTO_QUERY_RESPONSE_FACTORY_HPP

#include "backend/protobuf/query_responses/proto_block_query_response.hpp"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it used?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If so fdecl can be used

protocol_specific_response->set_reason(reason);

return std::make_unique<shared_model::proto::ErrorQueryResponse>(
std::move(protocol_query_response));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what about setting the message?

iroha::protocol::BlockResponse *protocol_specific_response =
protocol_query_response.mutable_block_response();
const auto &proto_block =
static_cast<const shared_model::proto::Block &>(block);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe explicitly set field without dependency on backend proto?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This class already depends on proto backend in other methods, could you please elaborate?

Copy link
Contributor

@l4l l4l Sep 18, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, yes there's no significant problem here. Although the code with casting to internal representation looks not that good

/**
* Describes type of error to be placed inside the error query response
*/
enum class ErrorQueryType {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it possible to reuse this list from somewhere?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Such enumeration exists also in the form of variant inside ErroQueryResponse, but it's impossible, I think, to reuse it

@@ -113,3 +112,13 @@ target_link_libraries(proto_block_factory_test
shared_model_proto_backend
shared_model_stateless_validation
)

if (IROHA_ROOT_PROJECT)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why it depends on root project?

Copy link
Contributor Author

@Akvinikym Akvinikym Sep 19, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because it uses internal part of shared_model_proto_backend, which, in turn, depends on root project. You can find it in "shared_model/backend/protobuf/CMakeLists.txt", line 47

* @return shared_ptr to result value or to nullptr, if result containts error
*/
template <typename ResultType, typename ErrorType>
std::shared_ptr<ResultType> unwrapResult(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Check out framework/result_fixture.hpp

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It cannot be applied here, because object_factory, after which the method unwrapResult is used, returns unique_ptr, and val from framework will try to copy it

ASSERT_EQ(response->accountAssets().front().accountId(), kAccountId);
ASSERT_EQ(response->accountAssets().front().assetId(), kAssetId);
for (auto i = 1; i < kAccountAssetsNumber; i++) {
ASSERT_EQ(response->accountAssets()[i - 1].balance(),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe just start with 0?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can, but in that case this 1 will be always added to balance, because the former cannot be equal to zero. I think, there's no difference

* @then that response is created @and is well-formed
*/
TEST_F(ProtoQueryResponseFactoryTest, CreateAccountDetailResponse) {
const DetailType account_details = "{ fav_meme : doge }";
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Doesn't really matter, but just for you knowledge, it's not a valid json

iroha::protocol::BlockResponse *protocol_specific_response =
protocol_query_response.mutable_block_response();
const auto &proto_block =
static_cast<const shared_model::proto::Block &>(block);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This class already depends on proto backend in other methods, could you please elaborate?

* @return account asset response
*/
virtual std::unique_ptr<AccountAssetResponse> createAccountAssetResponse(
const std::vector<
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider passing a value instead, so it is possible to either move or copy it from outer scope. Same applies to other methods.

* @param assets to be inserted into the response
* @return account asset response
*/
virtual std::unique_ptr<AccountAssetResponse> createAccountAssetResponse(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AccountAssetResponse -> QueryResponse, same for other methods, other than block query response.
Query hash also has to be passed as arguments.

@Akvinikym Akvinikym dismissed stale reviews from lebdron and l4l September 19, 2018 13:09

Fixed

@l4l
Copy link
Contributor

l4l commented Sep 23, 2018

Build is failing :(

l4l
l4l previously requested changes Sep 23, 2018
Copy link
Contributor

@l4l l4l left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

and this plz^

static_cast<const shared_model::proto::Account &>(account)
.getTransport());
*protocol_specific_response->mutable_account() =
static_cast<shared_model::proto::Account *>(account.release())
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like a memleak

virtual std::unique_ptr<QueryResponse> createAccountAssetResponse(
std::vector<std::shared_ptr<shared_model::interface::AccountAsset>>
assets,
const crypto::Hash &query_hash) = 0;

/**
* Create response for account detail query
* @param account_detail to be inserted into the response
* @return account detail response
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

missed query_hash notice in doc

createRolePermissionsResponse(
const RolePermissionSet &role_permissions) = 0;
virtual std::unique_ptr<QueryResponse> createRolePermissionsResponse(
RolePermissionSet role_permissions,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why by value?
Same for the rest in that file

Copy link
Contributor Author

@Akvinikym Akvinikym Sep 24, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We decided to pass args by values, so that client will decide, to copy or to move them, and we can do whatever we want with them. Move by ourselves, for example, to initialize some of factory's results. It's not possible now, but later it may become useful

}
ASSERT_TRUE(query_response);
ASSERT_EQ(query_response->queryHash(), kQueryHash);
ASSERT_NO_THROW({
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is really hard to determine with such block where is the issue. If exception is triggered, than the line of that won't be noticed. It may leave "as is", though would be nice if you come up with the better idea of such situation

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will add SCOPED_TRACE-s, this will help to at least understand, if SpecifiedVisitor worked correctly


auto stateless_invalid_response = response_factory->createErrorQueryResponse(
ErrorTypes::kStatelessFailed, kStatelessErrorMsg, kQueryHash);
auto no_signatories_response = response_factory->createErrorQueryResponse(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

out of the pr, but strange that both of methods used in one test

@@ -59,6 +60,8 @@ class ProtoQueryResponseFactoryTest : public ::testing::Test {
* @then that response is created @and is well-formed
*/
TEST_F(ProtoQueryResponseFactoryTest, CreateAccountAssetResponse) {
const HashType kQueryHash{Blob{"my_super_hash"}};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

there's Hash(const std::string&) afair

Signed-off-by: Akvinikym <[email protected]>
iroha::protocol::AccountAssetResponse *protocol_specific_response =
protocol_query_response.mutable_account_assets_response();
for (const auto &asset : assets) {
protocol_specific_response->add_account_assets()->CopyFrom(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No need to CopyFrom, *protocol_specific_response->add_account_assets() = getTransport() calls copy constructor. Same for other methods.


std::unique_ptr<shared_model::interface::QueryResponse>
shared_model::proto::ProtoQueryResponseFactory::createAccountAssetResponse(
std::vector<std::shared_ptr<shared_model::interface::AccountAsset>> assets,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not vector<unique_ptr>, so that it is possible to move the assets to query response? Same in createTransactionsResponse

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

unique_ptr seems not that handy to use, since most of the methods in iroha works with shared_ptr

std::vector<std::shared_ptr<shared_model::interface::AccountAsset>> assets,
const crypto::Hash &query_hash) {
iroha::protocol::QueryResponse protocol_query_response;
protocol_query_response.set_query_hash(query_hash.hex());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please create a common method for this, so these lines are not duplicated in all the methods.

iroha::protocol::QueryResponse protocol_query_response;
protocol_query_response.set_query_hash(query_hash.hex());
...
return std::make_unique<shared_model::proto::QueryResponse>(
      std::move(protocol_query_response));

Maybe create a method, so that it is possible to pass something in place of ...?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Imo it's better leave as is, otherwise code will be harder to read and modify

iroha::protocol::RolesResponse *protocol_specific_response =
protocol_query_response.mutable_roles_response();
for (const auto &role : roles) {
protocol_specific_response->add_roles(role);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It could be add_roles(std::move(role)) if const is removed above.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it also possible to use auto &&role, btw


#include <gtest/gtest.h>
#include <boost/optional.hpp>

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This empty line is redundant according to codestyle.

std::make_shared<ProtoCommonObjectsFactory<FieldValidator>>();

/**
* Put value of Result<unique_ptr<_>, _> into a shared_ptr
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Doc is outdated, please fix. Methods returns unique_ptr instead of shared_ptr.

}

void SetUp() override {}
void TearDown() override {}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These two overrides do nothing, please remove.

ASSERT_EQ(query_response->queryHash(), kQueryHash);
ASSERT_NO_THROW({
const auto &response = boost::apply_visitor(
SpecifiedVisitor<shared_model::interface::AccountAssetResponse>(),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SpecifiedVisitor can be replaced with boost::get<const T&> (const & in case of interface), since both return value or throw an exception.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A scoped trace will not be required if boost::get is used.


std::vector<std::shared_ptr<shared_model::interface::AccountAsset>> assets;
for (auto i = 1; i < kAccountAssetsNumber; ++i) {
auto asset = unwrapResult(objects_factory->createAccountAsset(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It should be possible to also replace unwrapResult with boost::get<Value<>> for simplicity.

Signed-off-by: Akvinikym <[email protected]>
@Akvinikym Akvinikym merged commit 5b4e5b2 into dev Sep 26, 2018
@Akvinikym Akvinikym deleted the feature/qry-resp-factory branch September 26, 2018 11:12
bakhtin pushed a commit that referenced this pull request Nov 2, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
needs-review pr awaits review from maintainers query All that relates to the iroha querying
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants