diff --git a/rd-cpp/src/rd_framework_cpp/src/main/impl/RdProperty.h b/rd-cpp/src/rd_framework_cpp/src/main/impl/RdProperty.h index 1828458e8..ed4ec6e15 100644 --- a/rd-cpp/src/rd_framework_cpp/src/main/impl/RdProperty.h +++ b/rd-cpp/src/rd_framework_cpp/src/main/impl/RdProperty.h @@ -43,20 +43,29 @@ class RdProperty final : public RdPropertyBase, public ISerializable static RdProperty read(SerializationCtx& ctx, Buffer& buffer) { RdId id = RdId::read(buffer); - bool not_null = buffer.read_bool(); // not null/ - (void) not_null; - auto value = S::read(ctx, buffer); RdProperty property; - property.value = std::move(value); withId(property, id); + const bool has_value = buffer.read_bool(); + if (has_value) + { + auto value = S::read(ctx, buffer); + property.value = std::move(value); + } return property; } void write(SerializationCtx& ctx, Buffer& buffer) const override { this->rdid.write(buffer); - buffer.write_bool(true); - S::write(ctx, buffer, this->get()); + if (this->has_value()) + { + buffer.write_bool(true); + S::write(ctx, buffer, this->get()); + } + else + { + buffer.write_bool(false); + } } void advise(Lifetime lifetime, std::function handler) const override diff --git a/rd-cpp/src/rd_framework_cpp/src/main/task/WiredRdTaskImpl.h b/rd-cpp/src/rd_framework_cpp/src/main/task/WiredRdTaskImpl.h index 259b25d58..ccc60c8f2 100644 --- a/rd-cpp/src/rd_framework_cpp/src/main/task/WiredRdTaskImpl.h +++ b/rd-cpp/src/rd_framework_cpp/src/main/task/WiredRdTaskImpl.h @@ -47,7 +47,7 @@ class WiredRdTaskImpl : public RdReactiveBase } template , bool> = true> - TaskResult bind_result(TaskResult result) const + TaskResult bind_result(TaskResult task_result) const { return result; } diff --git a/rd-cpp/src/rd_framework_cpp/src/test/cases/RdTaskTest.cpp b/rd-cpp/src/rd_framework_cpp/src/test/cases/RdTaskTest.cpp index 6b7132052..dd49db687 100644 --- a/rd-cpp/src/rd_framework_cpp/src/test/cases/RdTaskTest.cpp +++ b/rd-cpp/src/rd_framework_cpp/src/test/cases/RdTaskTest.cpp @@ -204,5 +204,35 @@ TEST_F(RdFrameworkTestBase, testAsyncBindableCall) EXPECT_TRUE(server_result_lifetime_terminated) << "Expected server lifetime for result to be terminated."; EXPECT_TRUE(server_result.unique()) << "Expected server_result to be released. Test should hold only reference to server result."; + AfterTest(); +} + +TEST_F(RdFrameworkTestBase, testUninitializedPropertyInResult) +{ + RdEndpoint server_entity; + RdCall client_entity; + + statics(server_entity, static_entity_id); + statics(client_entity, static_entity_id); + + Wrapper server_result; + + server_entity.set([&](std::wstring const&) + { + server_result = wrapper::make_wrapper(); + return server_result; + }); + + bindStatic(serverProtocol.get(), server_entity, static_name); + bindStatic(clientProtocol.get(), client_entity, static_name); + + auto task_result = client_entity.start(L"xy").value_or_throw(); + auto client_result = task_result.get_value(); + auto& foo_property = client_result->get_foo(); + EXPECT_THROW(foo_property.get(), std::exception) << "Expected to throw when access unitialized property"; + + server_result->get_foo().set(2); + EXPECT_EQ(2, foo_property.get()) << "Expected to sync property value when it set on server."; + AfterTest(); } \ No newline at end of file