Skip to content

Commit 530bfce

Browse files
authored
Merge pull request #432 from sony/remove-read-only-sequence-item-bug
IS-12: Fix remove_sequence_item control protocol method
2 parents a0723ad + b99e9d6 commit 530bfce

5 files changed

+164
-6
lines changed

Development/cmake/NmosCppTest.cmake

+1
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ set(NMOS_CPP_TEST_NMOS_TEST_SOURCES
4444
nmos/test/capabilities_test.cpp
4545
nmos/test/channels_test.cpp
4646
nmos/test/control_protocol_test.cpp
47+
nmos/test/control_protocol_methods_test.cpp
4748
nmos/test/did_sdid_test.cpp
4849
nmos/test/event_type_test.cpp
4950
nmos/test/json_validator_test.cpp

Development/nmos/control_protocol_methods.cpp

+12-1
Original file line numberDiff line numberDiff line change
@@ -296,7 +296,7 @@ namespace nmos
296296
}
297297

298298
// Delete sequence item
299-
web::json::value remove_sequence_item(nmos::resources& resources, const nmos::resource& resource, const web::json::value& arguments, bool is_deprecated, get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, slog::base_gate& gate)
299+
web::json::value remove_sequence_item(nmos::resources& resources, const nmos::resource& resource, const web::json::value& arguments, bool is_deprecated, get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, control_protocol_property_changed_handler property_changed, slog::base_gate& gate)
300300
{
301301
// note, model mutex is already locked by the outer function, so access to control_protocol_resources is OK...
302302

@@ -309,6 +309,11 @@ namespace nmos
309309
const auto& property = find_property_descriptor(details::parse_nc_property_id(property_id), details::parse_nc_class_id(nmos::fields::nc::class_id(resource.data)), get_control_protocol_class_descriptor);
310310
if (!property.is_null())
311311
{
312+
if (nmos::fields::nc::is_read_only(property))
313+
{
314+
return details::make_nc_method_result({ nc_method_status::read_only });
315+
}
316+
312317
const auto& data = resource.data.at(nmos::fields::nc::name(property));
313318

314319
if (!nmos::fields::nc::is_sequence(property) || data.is_null() || !data.is_array())
@@ -327,6 +332,12 @@ namespace nmos
327332
auto& sequence = resource.data[nmos::fields::nc::name(property)].as_array();
328333
sequence.erase(index);
329334

335+
// do notification that the specified property has changed
336+
if (property_changed)
337+
{
338+
property_changed(resource, nmos::fields::nc::name(property), index);
339+
}
340+
330341
}, make_property_changed_event(nmos::fields::nc::oid(resource.data), { { details::parse_nc_property_id(property_id), nc_property_change_type::type::sequence_item_removed, nc_id(index) } }));
331342

332343
return details::make_nc_method_result({ is_deprecated ? nmos::nc_method_status::method_deprecated : nmos::fields::nc::is_deprecated(property) ? nc_method_status::property_deprecated : nc_method_status::ok });

Development/nmos/control_protocol_methods.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ namespace nmos
2323
// Add item to sequence
2424
web::json::value add_sequence_item(nmos::resources& resources, const nmos::resource& resource, const web::json::value& arguments, bool is_deprecated, get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, get_control_protocol_datatype_descriptor_handler, control_protocol_property_changed_handler property_changed, slog::base_gate& gate);
2525
// Delete sequence item
26-
web::json::value remove_sequence_item(nmos::resources& resources, const nmos::resource& resource, const web::json::value& arguments, bool is_deprecated, get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, slog::base_gate& gate);
26+
web::json::value remove_sequence_item(nmos::resources& resources, const nmos::resource& resource, const web::json::value& arguments, bool is_deprecated, get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, control_protocol_property_changed_handler property_changed, slog::base_gate& gate);
2727
// Get sequence length
2828
web::json::value get_sequence_length(nmos::resources& resources, const nmos::resource& resource, const web::json::value& arguments, bool is_deprecated, get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, slog::base_gate& gate);
2929

Development/nmos/control_protocol_state.cpp

+4-4
Original file line numberDiff line numberDiff line change
@@ -122,11 +122,11 @@ namespace nmos
122122
return add_sequence_item(resources, resource, arguments, is_deprecated, get_control_protocol_class_descriptor, get_control_protocol_datatype_descriptor, property_changed, gate);
123123
};
124124
}
125-
nmos::experimental::control_protocol_method_handler make_nc_remove_sequence_item_handler(get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor)
125+
nmos::experimental::control_protocol_method_handler make_nc_remove_sequence_item_handler(get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, control_protocol_property_changed_handler property_changed)
126126
{
127-
return [get_control_protocol_class_descriptor](nmos::resources& resources, const nmos::resource& resource, const web::json::value& arguments, bool is_deprecated, slog::base_gate& gate)
127+
return [get_control_protocol_class_descriptor, property_changed](nmos::resources& resources, const nmos::resource& resource, const web::json::value& arguments, bool is_deprecated, slog::base_gate& gate)
128128
{
129-
return remove_sequence_item(resources, resource, arguments, is_deprecated, get_control_protocol_class_descriptor, gate);
129+
return remove_sequence_item(resources, resource, arguments, is_deprecated, get_control_protocol_class_descriptor, property_changed, gate);
130130
};
131131
}
132132
nmos::experimental::control_protocol_method_handler make_nc_get_sequence_length_handler(get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor)
@@ -230,7 +230,7 @@ namespace nmos
230230
{ nc_object_get_sequence_item_method_id, details::make_nc_get_sequence_item_handler(get_control_protocol_class_descriptor) },
231231
{ nc_object_set_sequence_item_method_id, details::make_nc_set_sequence_item_handler(get_control_protocol_class_descriptor, get_control_protocol_datatype_descriptor, property_changed) },
232232
{ nc_object_add_sequence_item_method_id, details::make_nc_add_sequence_item_handler(get_control_protocol_class_descriptor, get_control_protocol_datatype_descriptor, property_changed) },
233-
{ nc_object_remove_sequence_item_method_id, details::make_nc_remove_sequence_item_handler(get_control_protocol_class_descriptor) },
233+
{ nc_object_remove_sequence_item_method_id, details::make_nc_remove_sequence_item_handler(get_control_protocol_class_descriptor, property_changed) },
234234
{ nc_object_get_sequence_length_method_id, details::make_nc_get_sequence_length_handler(get_control_protocol_class_descriptor) }
235235
}),
236236
// NcObject events
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
// The first "test" is of course whether the header compiles standalone
2+
#include "boost/iostreams/stream.hpp"
3+
#include "boost/iostreams/device/null.hpp"
4+
#include "nmos/control_protocol_resource.h"
5+
#include "nmos/control_protocol_resources.h"
6+
#include "nmos/control_protocol_methods.h"
7+
#include "nmos/control_protocol_state.h"
8+
#include "nmos/control_protocol_typedefs.h"
9+
#include "nmos/control_protocol_utils.h"
10+
#include "nmos/is12_versions.h"
11+
#include "nmos/json_fields.h"
12+
#include "nmos/log_gate.h"
13+
#include "nmos/slog.h"
14+
#include "bst/test/test.h"
15+
16+
17+
////////////////////////////////////////////////////////////////////////////////////////////
18+
BST_TEST_CASE(testRemoveSequenceItem)
19+
{
20+
using web::json::value_of;
21+
using web::json::value;
22+
23+
bool property_changed_called = false;
24+
25+
boost::iostreams::stream< boost::iostreams::null_sink > null_ostream((boost::iostreams::null_sink()));
26+
27+
nmos::experimental::log_model log_model;
28+
nmos::experimental::log_gate gate(null_ostream, null_ostream, log_model);
29+
30+
nmos::resources resources;
31+
nmos::control_protocol_property_changed_handler property_changed = [&property_changed_called](const nmos::resource& resource, const utility::string_t& property_name, int index)
32+
{
33+
// check that the property changed handler gets called
34+
property_changed_called = true;
35+
};
36+
nmos::experimental::control_protocol_state control_protocol_state(property_changed);
37+
nmos::get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor = nmos::make_get_control_protocol_class_descriptor_handler(control_protocol_state);
38+
39+
40+
// Create simple non-standard class with writable sequence property
41+
const auto writable_sequence_class_id = nmos::make_nc_class_id(nmos::nc_worker_class_id, -1234, { 1000 });
42+
const web::json::field_as_array writable_value{ U("writableValue") };
43+
{
44+
// Writable sequence_class property descriptors
45+
std::vector<web::json::value> writable_sequence_property_descriptors = { nmos::experimental::make_control_class_property_descriptor(U("Writable sequence"), { 3, 1 }, writable_value, U("NcInt16"), false, false, true, false, web::json::value::null()) };
46+
47+
// create writable_sequence class descriptor
48+
auto writable_sequence_class_descriptor = nmos::experimental::make_control_class_descriptor(U("Writable sequence class descriptor"), writable_sequence_class_id, U("WritableSequence"), writable_sequence_property_descriptors);
49+
50+
// insert writable_sequence class descriptor to global state, which will be used by the control_protocol_ws_message_handler to process incoming ws message
51+
control_protocol_state.insert(writable_sequence_class_descriptor);
52+
}
53+
// helper function to create writable_sequence object
54+
auto make_writable_sequence = [&writable_value, &writable_sequence_class_id](nmos::nc_oid oid, nmos::nc_oid owner, const utility::string_t& role, const utility::string_t& user_label, const utility::string_t& description)
55+
{
56+
auto data = nmos::details::make_nc_worker(writable_sequence_class_id, oid, true, owner, role, value::string(user_label), description, web::json::value::null(), web::json::value::null(), true);
57+
auto values = value::array();
58+
web::json::push_back(values, value::number(10));
59+
web::json::push_back(values, value::number(9));
60+
web::json::push_back(values, value::number(8));
61+
data[writable_value] = values;
62+
63+
return nmos::control_protocol_resource{ nmos::is12_versions::v1_0, nmos::types::nc_worker, std::move(data), true };
64+
};
65+
66+
// Create Device Model
67+
// root
68+
auto root_block = nmos::make_root_block();
69+
auto oid = nmos::root_block_oid;
70+
// root, ClassManager
71+
auto class_manager = nmos::make_class_manager(++oid, control_protocol_state);
72+
auto receiver_block_oid = ++oid;
73+
// root, receivers
74+
auto receivers = nmos::make_block(receiver_block_oid, nmos::root_block_oid, U("receivers"), U("Receivers"), U("Receivers block"));
75+
auto receivers_id = receivers.id;
76+
77+
// root, receivers, mon1
78+
auto monitor1 = nmos::make_receiver_monitor(++oid, true, receiver_block_oid, U("mon1"), U("monitor 1"), U("monitor 1"), value::null());
79+
// root, receivers, mon2
80+
auto monitor2 = nmos::make_receiver_monitor(++oid, true, receiver_block_oid, U("mon2"), U("monitor 2"), U("monitor 2"), value::null());
81+
82+
auto writable_sequence = make_writable_sequence(++oid, nmos::root_block_oid, U("writableSequence"), U("writable sequence"), U("writable sequence"));
83+
auto writable_sequence_id = writable_sequence.id;
84+
85+
nmos::push_back(receivers, monitor1);
86+
// add example-control to root-block
87+
nmos::push_back(receivers, monitor2);
88+
// add stereo-gain to root-block
89+
nmos::push_back(root_block, receivers);
90+
// add class-manager to root-block
91+
nmos::push_back(root_block, class_manager);
92+
// add writable sequence to root block
93+
nmos::push_back(root_block, writable_sequence);
94+
insert_resource(resources, std::move(root_block));
95+
insert_resource(resources, std::move(class_manager));
96+
insert_resource(resources, std::move(receivers));
97+
insert_resource(resources, std::move(monitor1));
98+
insert_resource(resources, std::move(monitor2));
99+
insert_resource(resources, std::move(writable_sequence));
100+
101+
// Attempt to remove a member from a block - read only error expected
102+
{
103+
property_changed_called = false;
104+
105+
auto block_members_property_id = value_of({
106+
{ U("level"), nmos::nc_block_members_property_id.level },
107+
{ U("index"), nmos::nc_block_members_property_id.index},
108+
});
109+
110+
auto arguments = value_of({
111+
{ nmos::fields::nc::id, block_members_property_id },
112+
{ nmos::fields::nc::index, 0}
113+
});
114+
115+
auto resource = nmos::find_resource(resources, receivers_id);
116+
BST_CHECK_NE(resources.end(), resource);
117+
auto result = nmos::remove_sequence_item(resources, *resource, arguments, false, get_control_protocol_class_descriptor, property_changed, gate);
118+
119+
// Expect read only error, and for property changed not to be called
120+
BST_CHECK_EQUAL(false, property_changed_called);
121+
BST_CHECK_EQUAL(nmos::nc_method_status::read_only, nmos::fields::nc::status(result));
122+
}
123+
124+
// Remove writable sequence item - success and property_changed event expected
125+
{
126+
property_changed_called = false;
127+
128+
auto writable_sequence_property_id = value_of({
129+
{ U("level"), 3 },
130+
{ U("index"), 1},
131+
});
132+
133+
auto arguments = value_of({
134+
{ nmos::fields::nc::id, writable_sequence_property_id },
135+
{ nmos::fields::nc::index, 1}
136+
});
137+
138+
auto resource = nmos::find_resource(resources, writable_sequence_id);
139+
BST_CHECK_NE(resources.end(), resource);
140+
auto result = nmos::remove_sequence_item(resources, *resource, arguments, false, get_control_protocol_class_descriptor, property_changed, gate);
141+
142+
// Expect success, and property changed event
143+
BST_CHECK_EQUAL(true, property_changed_called);
144+
BST_CHECK_EQUAL(nmos::nc_method_status::ok, nmos::fields::nc::status(result));
145+
}
146+
}

0 commit comments

Comments
 (0)