use parking_lot::Mutex;
use std::sync::Arc;
use std::{io::Cursor, str::FromStr};
use crate::types::{encoding::DecodingOptions, string::UAString, tests::*};
#[test]
fn encoding_bool() {
serialize_test(true);
serialize_test(false);
}
#[test]
fn encoding_sbyte() {
serialize_test(0 as i8);
serialize_test(100 as i8);
serialize_test(-90 as i8);
}
#[test]
fn encoding_byte() {
serialize_test(0 as u8);
serialize_test(255 as u8);
serialize_test(90 as u8);
}
#[test]
fn encoding_int16() {
serialize_test(0 as i16);
serialize_test(-17000 as i16);
serialize_test(32000 as i16);
}
#[test]
fn encoding_uint16() {
serialize_test(0 as u16);
serialize_test(57000 as u16);
serialize_test(32000 as u16);
}
#[test]
fn encoding_int32() {
serialize_test(0 as i32);
serialize_test(-17444000 as i32);
serialize_test(32004440 as i32);
}
#[test]
fn encoding_uint32() {
serialize_test(0 as u32);
serialize_test(57055500 as u32);
serialize_test(32555000 as u32);
}
#[test]
fn encoding_int64() {
serialize_test(0 as i64);
serialize_test(-17442224000 as i64);
serialize_test(32022204440 as i64);
}
#[test]
fn encoding_uint64() {
serialize_test(0 as u64);
serialize_test(57054445500 as u64);
serialize_test(34442555000 as u64);
}
#[test]
fn encoding_f32() {
serialize_test(0 as f32);
serialize_test(12.4342 as f32);
serialize_test(5686.222 as f32);
}
#[test]
fn encoding_f64() {
serialize_test(0 as f64);
serialize_test(12.43424324234 as f64);
serialize_test(5686.222342342 as f64);
}
#[test]
fn encoding_string() {
serialize_test(UAString::null());
serialize_test(UAString::from(""));
serialize_test(UAString::from("ショッピング"));
serialize_test(UAString::from("This is a test"));
}
#[test]
fn encode_string_part_6_5224() {
let expected = [0x06, 0x00, 0x00, 0x00, 0xE6, 0xB0, 0xB4, 0x42, 0x6F, 0x79];
let input = UAString::from("æ°´Boy");
serialize_and_compare(input, &expected);
}
#[test]
fn decode_string_malformed_utf8() {
let bytes = [0x06, 0x00, 0x00, 0xE6, 0xB0, 0xB4, 0x42, 0x6F, 0x79];
let mut stream = Cursor::new(bytes);
let decoding_options = DecodingOptions::test();
assert_eq!(
UAString::decode(&mut stream, &decoding_options).unwrap_err(),
StatusCode::BadDecodingError
);
}
#[test]
fn encoding_datetime() {
let now = DateTime::now();
serialize_test(now);
let epoch = DateTime::epoch();
serialize_test(epoch);
let endtimes = DateTime::endtimes();
serialize_test(endtimes);
let before_epoch = DateTime::ymd_hms(1599, 1, 1, 0, 0, 0);
serialize_test_expected(before_epoch, DateTime::epoch());
let after_endtimes = DateTime::ymd_hms(10000, 1, 1, 0, 0, 0);
serialize_test_expected(after_endtimes, DateTime::endtimes());
}
#[test]
fn encoding_guid() {
let guid = Guid::from_str("F0001234-FACE-BEEF-0102-030405060708").unwrap();
assert_eq!(
"f0001234-face-beef-0102-030405060708",
format!("{:?}", guid)
);
let new_guid = serialize_test_and_return(guid.clone());
assert_eq!(
"f0001234-face-beef-0102-030405060708",
format!("{:?}", new_guid)
);
serialize_test(guid);
}
#[test]
fn encode_guid_5226() {
let expected_bytes = [
0x91, 0x2B, 0x96, 0x72, 0x75, 0xFA, 0xE6, 0x4A, 0x8D, 0x28, 0xB4, 0x04, 0xDC, 0x7D, 0xAF,
0x63,
];
let guid = Guid::from_str("912b9672-75fa-e64a-8D28-B404DC7DAF63").unwrap();
serialize_and_compare(guid, &expected_bytes);
}
#[test]
fn node_id_2byte_numeric() {
let node_id = NodeId::new(0, 0x72 as u32);
let expected_bytes = [0x0, 0x72];
serialize_and_compare(node_id.clone(), &expected_bytes);
serialize_test(node_id);
}
#[test]
fn node_id_4byte_numeric() {
let node_id = NodeId::new(5, 1025);
assert!(node_id.is_numeric());
let expected_bytes = [0x1, 0x5, 0x1, 0x4];
serialize_and_compare(node_id, &expected_bytes);
let node_id = NodeId::new(5, 1025);
serialize_test(node_id);
}
#[test]
fn node_id_large_namespace() {
let node_id = NodeId::new(0x100, 1);
assert!(node_id.is_numeric());
let expected_bytes = [0x2, 0x0, 0x1, 0x1, 0x0, 0x0, 0x0];
serialize_and_compare(node_id.clone(), &expected_bytes);
serialize_test(node_id);
}
#[test]
fn node_id_large_id() {
let node_id = NodeId::new(1, 0xdeadbeef as u32);
assert!(node_id.is_numeric());
let expected_bytes = [0x2, 0x1, 0x0, 0xef, 0xbe, 0xad, 0xde];
serialize_and_compare(node_id.clone(), &expected_bytes);
serialize_test(node_id);
}
#[test]
fn node_id_string_part_6_5229() {
let node_id = NodeId::new(1, "Hotæ°´");
assert!(node_id.is_string());
let expected_bytes = [
0x03, 0x1, 0x0, 0x6, 0x0, 0x0, 0x0, 0x48, 0x6F, 0x74, 0xE6, 0xB0, 0xB4,
];
serialize_and_compare(node_id.clone(), &expected_bytes);
serialize_test(node_id);
}
#[test]
fn node_id_guid() {
let guid = Guid::from_str("912b9672-75fa-e64a-8D28-B404DC7DAF63").unwrap();
let node_id = NodeId::new(1, guid);
assert!(node_id.is_guid());
serialize_test(node_id);
}
#[test]
fn node_id_byte_string() {
serialize_test(ByteString::null());
let node_id = NodeId::new(30, ByteString::from(b"this is a byte string"));
assert!(node_id.is_byte_string());
serialize_test(node_id);
}
#[test]
fn extension_object() {
let eo = ExtensionObject::null();
serialize_test(eo);
let eo = ExtensionObject {
node_id: ObjectId::CreateSessionResponse_Encoding_DefaultBinary.into(),
body: ExtensionObjectEncoding::ByteString(ByteString::from(b"hello world")),
};
serialize_test(eo);
let eo = ExtensionObject {
node_id: ObjectId::CreateSessionResponse_Encoding_DefaultBinary.into(),
body: ExtensionObjectEncoding::XmlElement(XmlElement::from("hello world")),
};
serialize_test(eo);
}
#[test]
fn localized_text() {
let t = LocalizedText {
locale: UAString::null(),
text: UAString::null(),
};
serialize_test(t);
let t = LocalizedText {
locale: UAString::from("Hello world"),
text: UAString::null(),
};
serialize_test(t);
let t = LocalizedText {
locale: UAString::null(),
text: UAString::from("Now is the winter of our discontent"),
};
serialize_test(t);
let t = LocalizedText {
locale: UAString::from("ABCDEFG"),
text: UAString::from("Now is the winter of our discontent"),
};
serialize_test(t);
}
#[test]
fn expanded_node_id() {
let node_id = ExpandedNodeId::new(NodeId::new(200, 2000));
serialize_test(node_id);
let mut node_id = ExpandedNodeId::new(NodeId::new(200, 2000));
node_id.namespace_uri = UAString::from("test");
serialize_test(node_id);
let mut node_id = ExpandedNodeId::new(NodeId::new(200, 2000));
node_id.server_index = 500;
serialize_test(node_id);
let mut node_id = ExpandedNodeId::new(NodeId::new(200, 2000));
node_id.namespace_uri = UAString::from("test2");
node_id.server_index = 50330;
serialize_test(node_id);
}
#[test]
fn qualified_name() {
let qname = QualifiedName {
namespace_index: 100,
name: UAString::from("this is a qualified name"),
};
serialize_test(qname);
}
#[test]
fn variant() {
use std::mem;
println!(
"Size of a variant in bytes is {}",
mem::size_of::<Variant>()
);
let v = Variant::Boolean(true);
serialize_test(v);
let v = Variant::SByte(-44);
serialize_test(v);
let v = Variant::Byte(255);
serialize_test(v);
let v = Variant::Int16(-20000);
serialize_test(v);
let v = Variant::UInt16(55778);
serialize_test(v);
let v = Variant::Int32(-9999999);
serialize_test(v);
let v = Variant::UInt32(24424244);
serialize_test(v);
let v = Variant::Int64(-384747424424244);
serialize_test(v);
let v = Variant::UInt64(9384747424422314244);
serialize_test(v);
let v = Variant::Float(77.33f32);
serialize_test(v);
let v = Variant::Double(99.123f64);
serialize_test(v);
let v = Variant::from(DateTime::now());
serialize_test(v);
let v = Variant::from(UAString::from("Hello Everybody"));
serialize_test(v);
let v = Variant::from(ByteString::from(b"Everything or nothing"));
serialize_test(v);
let v = Variant::from(XmlElement::from("The world wonders"));
serialize_test(v);
let v: NodeId = ObjectId::AddNodesItem_Encoding_DefaultBinary.into();
let v = Variant::from(v);
serialize_test(v);
let v = Variant::from(NodeId::new(99, "hello everyone"));
serialize_test(v);
let v: ExpandedNodeId = ObjectId::AddNodesItem_Encoding_DefaultBinary.into();
let v = Variant::from(v);
serialize_test(v);
let v = Variant::from(StatusCode::BadTcpMessageTypeInvalid);
serialize_test(v);
let v = Variant::from(QualifiedName {
namespace_index: 100,
name: UAString::from("this is a qualified name"),
});
serialize_test(v);
let v = Variant::from(LocalizedText {
locale: UAString::from("Hello everyone"),
text: UAString::from("This text is localized"),
});
serialize_test(v);
let v = Variant::from(ExtensionObject::null());
serialize_test(v);
let v = Variant::from(DataValue {
value: Some(Variant::Double(1000f64)),
status: Some(StatusCode::GoodClamped),
source_timestamp: Some(DateTime::now()),
source_picoseconds: Some(333),
server_timestamp: Some(DateTime::now()),
server_picoseconds: Some(666),
});
serialize_test(v);
let v = Variant::Variant(Box::new(Variant::from(8u8)));
serialize_test(v);
let v = Variant::from(DiagnosticInfo {
symbolic_id: Some(99),
namespace_uri: Some(437437),
locale: Some(333),
localized_text: Some(233),
additional_info: Some(UAString::from("Nested diagnostic")),
inner_status_code: Some(StatusCode::Good),
inner_diagnostic_info: None,
});
serialize_test(v);
let v = DataValue {
value: Some(Variant::Double(1000f64)),
status: Some(StatusCode::GoodClamped),
source_timestamp: Some(DateTime::now()),
source_picoseconds: Some(333),
server_timestamp: Some(DateTime::now()),
server_picoseconds: Some(666),
};
serialize_test(v);
}
#[test]
fn variant_single_dimension_array() {
let values = vec![
Variant::Int32(100),
Variant::Int32(200),
Variant::Int32(300),
];
let v = Variant::from((VariantTypeId::Int32, values));
serialize_test(v);
}
#[test]
fn variant_multi_dimension_array() {
let values = vec![
Variant::Int32(100),
Variant::Int32(200),
Variant::Int32(300),
Variant::Int32(400),
Variant::Int32(500),
Variant::Int32(600),
];
let dimensions = vec![3u32, 2u32];
let v = Variant::from((VariantTypeId::Int32, values, dimensions));
serialize_test(v);
}
#[test]
fn diagnostic_info() {
let mut d = DiagnosticInfo {
symbolic_id: None,
namespace_uri: None,
locale: None,
localized_text: None,
additional_info: None,
inner_status_code: None,
inner_diagnostic_info: None,
};
serialize_test(d.clone());
d.symbolic_id = Some(25);
assert_eq!(d.encoding_mask().bits(), 0x1);
d.namespace_uri = Some(100);
assert_eq!(d.encoding_mask().bits(), 0x3);
d.localized_text = Some(120);
assert_eq!(d.encoding_mask().bits(), 0x7);
d.locale = Some(110);
assert_eq!(d.encoding_mask().bits(), 0xf);
d.additional_info = Some(UAString::from("Hello world"));
assert_eq!(d.encoding_mask().bits(), 0x1f);
d.inner_status_code = Some(StatusCode::BadArgumentsMissing);
assert_eq!(d.encoding_mask().bits(), 0x3f);
serialize_test(d.clone());
d.inner_diagnostic_info = Some(Box::new(DiagnosticInfo {
symbolic_id: Some(99),
namespace_uri: Some(437437),
locale: Some(333),
localized_text: Some(233),
additional_info: Some(UAString::from("Nested diagnostic")),
inner_status_code: Some(StatusCode::Good),
inner_diagnostic_info: None,
}));
serialize_test(d.clone());
}
#[test]
fn argument() {
serialize_test(Argument {
name: UAString::from("arg"),
data_type: NodeId::null(),
value_rank: 1,
array_dimensions: Some(vec![10]),
description: LocalizedText::new("foo", "bar"),
});
}
#[test]
fn null_array() -> EncodingResult<()> {
let vec = Vec::new();
let mut stream = Cursor::new(vec);
let mask = EncodingMask::BOOLEAN | EncodingMask::ARRAY_MASK;
mask.encode(&mut stream)?;
let length = -1_i32;
length.encode(&mut stream)?;
let actual = stream.into_inner();
let mut stream = Cursor::new(actual);
let arr = Variant::decode(&mut stream, &DecodingOptions::test())?;
assert_eq!(
arr,
Variant::Array(Box::new(Array {
value_type: VariantTypeId::Boolean,
values: Vec::new(),
dimensions: Some(Vec::new())
}))
);
Ok(())
}
#[test]
fn deep_encoding() {
let decoding_options = DecodingOptions {
decoding_depth_gauge: Arc::new(Mutex::new(DepthGauge {
max_depth: 2,
current_depth: 0,
})),
..Default::default()
};
let _n = NodeId::new(2, "Hello world");
let d4 = Variant::from(1);
let d3 = Variant::Variant(Box::new(d4));
let d2 = Variant::Variant(Box::new(d3));
let mut stream = serialize_as_stream(d2.clone());
assert_eq!(Variant::decode(&mut stream, &decoding_options).unwrap(), d2);
let d1 = Variant::Variant(Box::new(d2));
let mut stream = serialize_as_stream(d1);
let res = Variant::decode(&mut stream, &decoding_options);
assert_eq!(res.unwrap_err(), StatusCode::BadDecodingError);
}
#[test]
fn depth_gauge() {
let dg = Arc::new(Mutex::new(DepthGauge::default()));
let max_depth = {
let dg = trace_lock!(dg);
dg.max_depth()
};
assert_eq!(max_depth, constants::MAX_DECODING_DEPTH);
{
let mut v = Vec::new();
for _ in 0..max_depth {
v.push(DepthLock::obtain(dg.clone()).unwrap());
}
{
let dg = trace_lock!(dg);
assert_eq!(dg.current_depth(), max_depth);
}
assert_eq!(
DepthLock::obtain(dg.clone()).unwrap_err(),
StatusCode::BadDecodingError
);
}
{
let dg = trace_lock!(dg);
assert_eq!(dg.current_depth(), 0);
}
}