Completed
Push — master ( f41327...987601 )
by Olivier
04:37 queued 01:54
created

tests.test_custom_structures   A

Complexity

Total Complexity 33

Size/Duplication

Total Lines 410
Duplicated Lines 4.88 %

Importance

Changes 0
Metric Value
eloc 319
dl 20
loc 410
rs 9.76
c 0
b 0
f 0
wmc 33

How to fix   Duplicated Code   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

1
import unittest
2
import logging
3
import xml.etree.ElementTree as Et
4
5
import pytest
6
7
from asyncua import ua, Server
8
import asyncua.common.type_dictionary_buider
9
from asyncua.common.type_dictionary_buider import OPCTypeDictionaryBuilder, DataTypeDictionaryBuilder
10
from asyncua.common.type_dictionary_buider import get_ua_class, StructNode
11
12
port_num = 48540
13
ns_urn = 'http://test.freeopcua.github.io'
14
15
16
pytestmark = pytest.mark.asyncio
17
18
19
def to_camel_case(name):
20
    func = getattr(asyncua.common.type_dictionary_buider, '_to_camel_case')
21
    return func(name)
22
23
24
def reference_generator(source_id, target_id, reference_type, is_forward=True):
25
    func = getattr(asyncua.common.type_dictionary_buider, '_reference_generator')
26
    return func(source_id, target_id, reference_type, is_forward)
27
28
29
def set_up_test_tree():
30
    ext_head_attributes = {'xmlns:xsi': 'http://www.w3.org/2001/XMLSchema-instance', 'xmlns:tns': ns_urn,
31
                           'DefaultByteOrder': 'LittleEndian', 'xmlns:opc': 'http://opcfoundation.org/BinarySchema/',
32
                           'xmlns:ua': 'http://opcfoundation.org/UA/', 'TargetNamespace': ns_urn}
33
34
    test_etree = Et.ElementTree(Et.Element('opc:TypeDictionary', ext_head_attributes))
35
    name_space = Et.SubElement(test_etree.getroot(), 'opc:Import')
36
    name_space.attrib['Namespace'] = 'http://opcfoundation.org/UA/'
37
    return test_etree
38
39
40
@pytest.fixture(scope="module")
41
async def _srv(server):
42
    class Srv:
43
        pass
44
    srv = Srv()
45
    srv.srv = server
46
    srv.idx = await srv.srv.register_namespace(ns_urn)
47
    yield srv
48
49
    
50
@pytest.fixture
51
async def srv(_srv):
52
    _srv.test_etree = set_up_test_tree()
53
    _srv.opc_type_builder = OPCTypeDictionaryBuilder(ns_urn)
54
    _srv.dict_builder = DataTypeDictionaryBuilder(_srv.srv, _srv.idx, ns_urn, 'TestDict')
55
    await _srv.dict_builder.init()
56
    _srv.init_counter = getattr(_srv.dict_builder, '_id_counter')
57
    yield _srv
58
    curr_counter = getattr(_srv.dict_builder, '_id_counter')
59
    trash_nodes = []
60
    for counter in range(_srv.init_counter, curr_counter + 1):
61
        trash_nodes.append(_srv.srv.get_node('ns={0};i={1}'.format(_srv.idx, str(counter))))
62
    await _srv.srv.delete_nodes(trash_nodes)
63
64
65
async def test_camel_case_1():
66
    case = 'TurtleActionlibShapeActionFeedback'
67
    result = to_camel_case('turtle_actionlib/ShapeActionFeedback')
68
    assert result == case
69
70
71
async def test_camel_case_2():
72
    case = 'HelloWorldFffD'
73
    result = to_camel_case('Hello#world+fff_**?&&d')
74
    assert result == case
75
76
77
async def test_opc_type_dict_process_type_opc(srv):
78
    case = 'opc:Boolean'
79
    result = getattr(srv.opc_type_builder, '_process_type')('Boolean')
80
    assert result == case
81
82
83
async def test_opc_type_dict_process_type_tns(srv):
84
    case = 'tns:CustomizedStruct'
85
    result = getattr(srv.opc_type_builder, '_process_type')('CustomizedStruct')
86
    assert result == case
87
88
89
async def test_opc_type_dict_append_struct_1(srv):
90
    case = {'BaseType': 'ua:ExtensionObject',
91
            'Name': 'CustomizedStruct'}
92
    result = srv.opc_type_builder.append_struct('CustomizedStruct')
93
    assert result.attrib == case
94
95
96
async def test_opc_type_dict_append_struct_2(srv):
97
    case = {'BaseType': 'ua:ExtensionObject',
98
            'Name': 'CustomizedStruct'}
99
    result = srv.opc_type_builder.append_struct('customized_#?+`struct')
100
    assert result.attrib == case
101
102
103
async def test_opc_type_dict_add_field_1(srv):
104
    structure_name = 'CustomizedStruct'
105
    srv.opc_type_builder.append_struct(structure_name)
106
    srv.opc_type_builder.add_field(ua.VariantType.Boolean, 'id', structure_name)
107
    case = {'TypeName': 'opc:Boolean',
108
            'Name': 'id'}
109
    struct_dict = getattr(srv.opc_type_builder, '_structs_dict')
110
    result = list(struct_dict[structure_name])[0]
111
    assert result.attrib == case
112
113
114
async def test_opc_type_dict_add_field_2(srv):
115
    structure_name = 'CustomizedStruct'
116
    srv.opc_type_builder.append_struct(structure_name)
117
    srv.opc_type_builder.add_field('Boolean', 'id', structure_name)
118
    case = {'TypeName': 'opc:Boolean',
119
            'Name': 'id'}
120
    struct_dict = getattr(srv.opc_type_builder, '_structs_dict')
121
    result = list(struct_dict[structure_name])[0]
122
    assert result.attrib == case
123
124
125
async def test_opc_type_dict_add_field_3(srv):
126
    structure_name = 'CustomizedStruct'
127
    srv.opc_type_builder.append_struct(structure_name)
128
    srv.opc_type_builder.add_field(ua.VariantType.Boolean, 'id', structure_name, is_array=True)
129
    case = [{'TypeName': 'opc:Int32',
130
            'Name': 'NoOfid'},
131
            {'TypeName': 'opc:Boolean',
132
             'LengthField': 'NoOfid',
133
             'Name': 'id'}]
134
    struct_dict = getattr(srv.opc_type_builder, '_structs_dict')
135
    result = [item.attrib for item in list(struct_dict[structure_name])]
136
    assert result == case
137
138
139
async def test_opc_type_dict_get_dict_value(srv):
140
    structure_name = 'CustomizedStruct'
141
    srv.opc_type_builder.append_struct(structure_name)
142
    # external tree operation
143
    appended_struct = Et.SubElement(srv.test_etree.getroot(), 'opc:StructuredType')
144
    appended_struct.attrib['BaseType'] = 'ua:ExtensionObject'
145
    appended_struct.attrib['Name'] = to_camel_case(structure_name)
146
147
    srv.opc_type_builder.add_field(ua.VariantType.Boolean, 'id', structure_name)
148
    # external tree operation
149
    field = Et.SubElement(appended_struct, 'opc:Field')
150
    field.attrib['Name'] = 'id'
151
    field.attrib['TypeName'] = 'opc:Boolean'
152
    case = Et.tostring(srv.test_etree.getroot(), encoding='utf-8').decode("utf-8").replace(' ', '')
153
    result = srv.opc_type_builder.get_dict_value().decode("utf-8").replace(' ', '').replace('\n', '')
154
    assert result == case
155
156
157
async def test_reference_generator_1(srv):
158
    id1 = ua.NodeId(1, namespaceidx=2, nodeidtype=ua.NodeIdType.Numeric)
159
    id2 = ua.NodeId(2, namespaceidx=2, nodeidtype=ua.NodeIdType.Numeric)
160
    ref = ua.NodeId(ua.ObjectIds.HasEncoding, 0)
161
    result = reference_generator(id1, id2, ref)
162
    assert result.IsForward
163
    assert result.ReferenceTypeId == ref
164
    assert result.SourceNodeId == id1
165
    assert result.TargetNodeClass == ua.NodeClass.DataType
166
    assert result.TargetNodeId == id2
167
168
169
async def test_reference_generator_2(srv):
170
    id1 = ua.NodeId(1, namespaceidx=2, nodeidtype=ua.NodeIdType.Numeric)
171
    id2 = ua.NodeId(2, namespaceidx=2, nodeidtype=ua.NodeIdType.Numeric)
172
    ref = ua.NodeId(ua.ObjectIds.HasEncoding, 0)
173
    result = reference_generator(id1, id2, ref, False)
174
    assert not result.IsForward
175
    assert result.ReferenceTypeId == ref
176
    assert result.SourceNodeId == id1
177
    assert result.TargetNodeClass == ua.NodeClass.DataType
178
    assert result.TargetNodeId == id2
179
180
181
async def test_data_type_dict_general(srv):
182
    assert srv.dict_builder.dict_id is not None
183
    assert getattr(srv.dict_builder, '_type_dictionary') is not None
184
185
186
async def test_data_type_dict_nodeid_generator(srv):
187
    nodeid_generator = getattr(srv.dict_builder, '_nodeid_generator')
188
    result = nodeid_generator()
189
    assert isinstance(result, ua.NodeId)
190
    assert str(result.Identifier).isdigit()
191
    assert result.NamespaceIndex == srv.idx
192
    setattr(srv.dict_builder, '_id_counter', srv.init_counter)
193
194
195
async def test_data_type_dict_add_dictionary(srv):
196
    add_dictionary = getattr(srv.dict_builder, '_add_dictionary')
197
    dict_name = 'TestDict'
198
    dict_node = srv.srv.get_node(await add_dictionary(dict_name))
199
    assert await dict_node.get_browse_name() == ua.QualifiedName(dict_name, srv.idx)
200
    assert await dict_node.get_node_class() == ua.NodeClass.Variable
201
    assert (await dict_node.get_parent()).nodeid == ua.NodeId(ua.ObjectIds.OPCBinarySchema_TypeSystem, 0)
202
    assert ua.NodeId(ua.ObjectIds.HasComponent, 0) == (await dict_node.get_references(refs=ua.ObjectIds.HasComponent))[0].ReferenceTypeId
203
    assert await dict_node.get_type_definition() == ua.NodeId(ua.ObjectIds.DataTypeDictionaryType, 0)
204
    assert await dict_node.get_display_name() == ua.LocalizedText(dict_name)
205
    assert await dict_node.get_data_type() == ua.NodeId(ua.ObjectIds.ByteString)
206
    assert await dict_node.get_value_rank() == -1
207
208
209
async def test_data_type_dict_create_data_type(srv):
210
    type_name = 'CustomizedStruct'
211
    created_type = await srv.dict_builder.create_data_type(type_name)
212
    assert isinstance(created_type, StructNode)
213
    # Test data type node
214
    type_node = srv.srv.get_node(created_type.data_type)
215
    assert await type_node.get_browse_name() == ua.QualifiedName(type_name, srv.idx)
216
    assert await type_node.get_node_class() == ua.NodeClass.DataType
217
    assert (await type_node.get_parent()).nodeid == ua.NodeId(ua.ObjectIds.Structure, 0)
218
    assert ua.NodeId(ua.ObjectIds.HasSubtype, 0) == (await type_node.get_references(refs=ua.ObjectIds.HasSubtype))[0].ReferenceTypeId
219
    assert await type_node.get_display_name() == ua.LocalizedText(type_name)
220
221
    # Test description node
222
    desc_node = (await srv.srv.get_node(srv.dict_builder.dict_id).get_children())[0]
223
    assert await desc_node.get_browse_name() == ua.QualifiedName(type_name, srv.idx)
224
    assert await desc_node.get_node_class() == ua.NodeClass.Variable
225
    assert (await desc_node.get_parent()).nodeid == srv.dict_builder.dict_id
226
    assert ua.NodeId(ua.ObjectIds.HasComponent, 0) == (await desc_node.get_references(refs=ua.ObjectIds.HasComponent))[0].ReferenceTypeId
227
    assert await desc_node.get_type_definition() == ua.NodeId(ua.ObjectIds.DataTypeDescriptionType, 0)
228
229
    assert await desc_node.get_display_name() == ua.LocalizedText(type_name)
230
    assert await desc_node.get_data_type() == ua.NodeId(ua.ObjectIds.String)
231
    assert await desc_node.get_value() == type_name
232
    assert await desc_node.get_value_rank() == -1
233
234
    # Test object node
235
    obj_node = (await type_node.get_children(refs=ua.ObjectIds.HasEncoding))[0]
236
    assert await obj_node.get_browse_name() == ua.QualifiedName('Default Binary', 0)
237
    assert await obj_node.get_node_class() == ua.NodeClass.Object
238
    assert (await obj_node.get_references(refs=ua.ObjectIds.HasEncoding))[0].NodeId == type_node.nodeid
239
    assert ua.NodeId(ua.ObjectIds.HasEncoding, 0) == (await obj_node.get_references(refs=ua.ObjectIds.HasEncoding))[0].ReferenceTypeId
240
    assert await obj_node.get_type_definition() == ua.NodeId(ua.ObjectIds.DataTypeEncodingType, 0)
241
    assert await obj_node.get_display_name() == ua.LocalizedText('Default Binary')
242
    assert len(await obj_node.get_event_notifier()) == 0
243
244
    # Test links, three were tested above
245
    struct_node = srv.srv.get_node(ua.NodeId(ua.ObjectIds.Structure, 0))
246
    struct_children = await struct_node.get_children(refs=ua.ObjectIds.HasSubtype)
247
    assert type_node in struct_children
248
    dict_node = srv.srv.get_node(srv.dict_builder.dict_id)
249
    dict_children = await dict_node.get_children(refs=ua.ObjectIds.HasComponent)
250
    assert desc_node in dict_children
251
    assert obj_node in await type_node.get_children(ua.ObjectIds.HasEncoding)
252
    assert desc_node in await obj_node.get_children(refs=ua.ObjectIds.HasDescription)
253
    assert obj_node.nodeid == (await desc_node.get_references(refs=ua.ObjectIds.HasDescription, direction=ua.BrowseDirection.Inverse))[0].NodeId
254
255
256
async def test_data_type_dict_set_dict_byte_string(srv):
257
    structure_name = 'CustomizedStruct'
258
    await srv.dict_builder.create_data_type(structure_name)
259
    srv.dict_builder.add_field(ua.VariantType.Int32, 'id', structure_name)
260
    await srv.dict_builder.set_dict_byte_string()
261
    # external tree operation
262
    appended_struct = Et.SubElement(srv.test_etree.getroot(), 'opc:StructuredType')
263
    appended_struct.attrib['BaseType'] = 'ua:ExtensionObject'
264
    appended_struct.attrib['Name'] = to_camel_case(structure_name)
265
266
    # external tree operation
267
    field = Et.SubElement(appended_struct, 'opc:Field')
268
    field.attrib['Name'] = 'id'
269
    field.attrib['TypeName'] = 'opc:Int32'
270
    case = Et.tostring(srv.test_etree.getroot(), encoding='utf-8').decode("utf-8").replace(' ', '')
271
    result = (await srv.srv.get_node(srv.dict_builder.dict_id).get_value()).decode("utf-8").replace(' ', '').replace('\n', '')
272
    assert result == case
273
274
275
async def test_data_type_dict_add_field_1(srv):
276
    struct_name = 'CustomizedStruct'
277
    await srv.dict_builder.create_data_type(struct_name)
278
    srv.dict_builder.add_field(ua.VariantType.Int32, 'id', struct_name)
279
    await srv.dict_builder.set_dict_byte_string()
280
    await srv.srv.load_type_definitions()
281
    struct = get_ua_class(struct_name)
282
    assert struct.ua_types[0][0] == 'id'
283
    assert struct.ua_types[0][1] == 'Int32'
284
    struct_instance = struct()
285
    assert struct_instance.id == 0
286
287
288
async def test_data_type_dict_add_field_2(srv):
289
    struct_name = 'AnotherCustomizedStruct'
290
    await srv.dict_builder.create_data_type(struct_name)
291
    srv.dict_builder.add_field(ua.VariantType.Int32, 'id', struct_name, is_array=True)
292
    await srv.dict_builder.set_dict_byte_string()
293
    await srv.srv.load_type_definitions()
294
    struct = get_ua_class(struct_name)
295
    assert struct.ua_types[0][0] == 'id'
296
    assert struct.ua_types[0][1] == 'ListOfInt32'
297
    struct_instance = struct()
298
    assert isinstance(struct_instance.id, list)
299
300
301
async def test_struct_node_general(srv):
302
    struct_name = 'CustomizedStruct'
303
    struct_node = await srv.dict_builder.create_data_type(struct_name)
304
    assert getattr(struct_node, '_type_dict'), srv.dict_builder
305
    assert isinstance(struct_node.data_type, ua.NodeId)
306
    assert struct_node.name == struct_name
307
308
309
async def test_struct_node_add_field(srv):
310
    struct_name = 'CustomizedStruct'
311
    struct_node = await srv.dict_builder.create_data_type(struct_name)
312
    struct_node.add_field('id', ua.VariantType.Int32)
313
    await srv.dict_builder.set_dict_byte_string()
314
    await srv.srv.load_type_definitions()
315
    struct = get_ua_class(struct_name)
316
    assert struct.ua_types[0][0] == 'id'
317
    assert struct.ua_types[0][1] == 'Int32'
318
    struct_instance = struct()
319
    assert struct_instance.id == 0
320
321
322
async def test_get_ua_class_1(srv):
323
    struct_name = 'CustomizedStruct'
324
    struct_node = await srv.dict_builder.create_data_type(struct_name)
325
    struct_node.add_field('id', ua.VariantType.Int32)
326
    await srv.dict_builder.set_dict_byte_string()
327
    await srv.srv.load_type_definitions()
328
    try:
329
        assert get_ua_class(struct_name) is not None
330
    except AttributeError:
331
        pass
332
333
334
async def test_get_ua_class_2(srv):
335
    struct_name = '*c*u_stom-ized&Stru#ct'
336
    struct_node = await srv.dict_builder.create_data_type(struct_name)
337
    struct_node.add_field('id', ua.VariantType.Int32)
338
    await srv.dict_builder.set_dict_byte_string()
339
    await srv.srv.load_type_definitions()
340
    try:
341
        assert get_ua_class(struct_name) is not None
342
    except AttributeError:
343
        pass
344
345
346
async def test_functional_basic(srv):
347
    basic_struct_name = 'basic_structure'
348
    basic_struct = await srv.dict_builder.create_data_type(basic_struct_name)
349
    basic_struct.add_field('ID', ua.VariantType.Int32)
350
    basic_struct.add_field('Gender', ua.VariantType.Boolean)
351
    basic_struct.add_field('Comments', ua.VariantType.String)
352
353
    await srv.dict_builder.set_dict_byte_string()
354
    await srv.srv.load_type_definitions()
355
356
    basic_var = await srv.srv.nodes.objects.add_variable(ua.NodeId(namespaceidx=srv.idx), 'BasicStruct',
357
                                                    ua.Variant(None, ua.VariantType.Null),
358
                                                    datatype=basic_struct.data_type)
359
360
    basic_msg = get_ua_class(basic_struct_name)()
361
    basic_msg.ID = 3
362
    basic_msg.Gender = True
363
    basic_msg.Comments = 'Test string'
364
    await basic_var.set_value(basic_msg)
365
366
    basic_result = await basic_var.get_value()
367
    assert basic_result == basic_msg
368
369
370
async def test_functional_advance(srv):
371
    basic_struct_name = 'basic_structure'
372
    basic_struct = await srv.dict_builder.create_data_type(basic_struct_name)
373
    basic_struct.add_field('ID', ua.VariantType.Int32)
374
    basic_struct.add_field('Gender', ua.VariantType.Boolean)
375
    basic_struct.add_field('Comments', ua.VariantType.String)
376
377
    nested_struct_name = 'nested_structure'
378
    nested_struct = await srv.dict_builder.create_data_type(nested_struct_name)
379
    nested_struct.add_field('Name', ua.VariantType.String)
380
    nested_struct.add_field('Surname', ua.VariantType.String)
381
    nested_struct.add_field('Stuff', basic_struct)
382
383
    await srv.dict_builder.set_dict_byte_string()
384
    await srv.srv.load_type_definitions()
385
386
    basic_var = await srv.srv.nodes.objects.add_variable(ua.NodeId(namespaceidx=srv.idx), 'BasicStruct',
387
                                                    ua.Variant(None, ua.VariantType.Null),
388
                                                    datatype=basic_struct.data_type)
389
390
    basic_msg = get_ua_class(basic_struct_name)()
391
    basic_msg.ID = 3
392
    basic_msg.Gender = True
393
    basic_msg.Comments = 'Test string'
394
    await basic_var.set_value(basic_msg)
395
396
    nested_var = await srv.srv.nodes.objects.add_variable(ua.NodeId(namespaceidx=srv.idx), 'NestedStruct',
397
                                                     ua.Variant(None, ua.VariantType.Null),
398
                                                     datatype=nested_struct.data_type)
399
400
    nested_msg = get_ua_class(nested_struct_name)()
401
    nested_msg.Stuff = basic_msg
402
    nested_msg.Name = 'Max'
403
    nested_msg.Surname = 'Karl'
404
    await nested_var.set_value(nested_msg)
405
406
    basic_result = await basic_var.get_value()
407
    assert basic_result == basic_msg
408
    nested_result = await nested_var.get_value()
409
    assert nested_result == nested_msg
410