PHP Classes

File: tests/Unit/Types/TypesTest.php

Recommend this page to a friend!
  Packages of Gianfrancesco Aurecchia   OPC UA Client   tests/Unit/Types/TypesTest.php   Download  
File: tests/Unit/Types/TypesTest.php
Role: Example script
Content type: text/plain
Description: Example script
Class: OPC UA Client
Control devices that support the OPC UA protocol
Author: By
Last change:
Date: 16 days ago
Size: 11,537 bytes
 

Contents

Class file image Download
<?php declare(strict_types=1); use PhpOpcua\Client\Types\BuiltinType; use PhpOpcua\Client\Types\DataValue; use PhpOpcua\Client\Types\EndpointDescription; use PhpOpcua\Client\Types\ExtensionObject; use PhpOpcua\Client\Types\LocalizedText; use PhpOpcua\Client\Types\NodeClass; use PhpOpcua\Client\Types\NodeId; use PhpOpcua\Client\Types\QualifiedName; use PhpOpcua\Client\Types\ReferenceDescription; use PhpOpcua\Client\Types\StatusCode; use PhpOpcua\Client\Types\UserTokenPolicy; use PhpOpcua\Client\Types\Variant; describe('StatusCode', function () { it('identifies Good status codes', function () { expect(StatusCode::isGood(StatusCode::Good))->toBeTrue(); expect(StatusCode::isBad(StatusCode::Good))->toBeFalse(); expect(StatusCode::isUncertain(StatusCode::Good))->toBeFalse(); }); it('identifies Bad status codes', function () { expect(StatusCode::isBad(StatusCode::BadNodeIdUnknown))->toBeTrue(); expect(StatusCode::isGood(StatusCode::BadNodeIdUnknown))->toBeFalse(); expect(StatusCode::isUncertain(StatusCode::BadNodeIdUnknown))->toBeFalse(); expect(StatusCode::isBad(StatusCode::BadInternalError))->toBeTrue(); expect(StatusCode::isBad(StatusCode::BadNotWritable))->toBeTrue(); expect(StatusCode::isBad(StatusCode::BadTypeMismatch))->toBeTrue(); expect(StatusCode::isBad(StatusCode::BadUserAccessDenied))->toBeTrue(); }); it('identifies Uncertain status codes', function () { expect(StatusCode::isUncertain(StatusCode::UncertainNoCommunicationLastUsableValue))->toBeTrue(); expect(StatusCode::isGood(StatusCode::UncertainNoCommunicationLastUsableValue))->toBeFalse(); expect(StatusCode::isBad(StatusCode::UncertainNoCommunicationLastUsableValue))->toBeFalse(); }); it('returns correct names for known codes', function () { expect(StatusCode::getName(StatusCode::Good))->toBe('Good'); expect(StatusCode::getName(StatusCode::BadNodeIdUnknown))->toBe('BadNodeIdUnknown'); expect(StatusCode::getName(StatusCode::BadNotWritable))->toBe('BadNotWritable'); expect(StatusCode::getName(StatusCode::BadInternalError))->toBe('BadInternalError'); expect(StatusCode::getName(StatusCode::UncertainNoCommunicationLastUsableValue))->toBe('UncertainNoCommunicationLastUsableValue'); }); it('returns hex string for unknown codes', function () { expect(StatusCode::getName(0x80FF0000))->toBe('0x80FF0000'); expect(StatusCode::getName(0x12345678))->toBe('0x12345678'); }); }); describe('QualifiedName', function () { it('returns name and namespace index', function () { $qn = new QualifiedName(2, 'TestNode'); expect($qn->getNamespaceIndex())->toBe(2); expect($qn->getName())->toBe('TestNode'); }); it('toString returns name only for namespace 0', function () { $qn = new QualifiedName(0, 'Server'); expect((string) $qn)->toBe('Server'); }); it('toString returns ns:name for non-zero namespace', function () { $qn = new QualifiedName(3, 'Variable'); expect((string) $qn)->toBe('3:Variable'); }); }); describe('DataValue', function () { it('returns null value when no variant', function () { $dv = new DataValue(); expect($dv->getValue())->toBeNull(); expect($dv->getVariant())->toBeNull(); expect($dv->getStatusCode())->toBe(0); expect($dv->getSourceTimestamp())->toBeNull(); expect($dv->getServerTimestamp())->toBeNull(); }); it('returns value from variant', function () { $variant = new Variant(BuiltinType::Int32, 42); $dv = new DataValue($variant); expect($dv->getValue())->toBe(42); expect($dv->getVariant())->toBe($variant); }); it('auto-extracts decoded ExtensionObject value', function () { $decoded = ['field1' => 'hello', 'field2' => 123]; $extObj = new ExtensionObject(NodeId::numeric(2, 5001), 0x01, null, $decoded); $variant = new Variant(BuiltinType::ExtensionObject, $extObj); $dv = new DataValue($variant); expect($extObj->isDecoded())->toBeTrue(); expect($dv->getValue())->toBe($decoded); }); it('encoding mask reflects set fields', function () { // Nothing set $dv = new DataValue(); expect($dv->getEncodingMask())->toBe(0); // Only value $dv = new DataValue(new Variant(BuiltinType::Boolean, true)); expect($dv->getEncodingMask())->toBe(0x01); // Value + bad status code $dv = new DataValue(new Variant(BuiltinType::Boolean, true), StatusCode::BadNotWritable); expect($dv->getEncodingMask())->toBe(0x03); // Value + source timestamp $dv = new DataValue(new Variant(BuiltinType::Int32, 1), 0, new DateTimeImmutable()); expect($dv->getEncodingMask())->toBe(0x05); // Value + server timestamp $dv = new DataValue(new Variant(BuiltinType::Int32, 1), 0, null, new DateTimeImmutable()); expect($dv->getEncodingMask())->toBe(0x09); // All fields $dv = new DataValue( new Variant(BuiltinType::Double, 3.14), StatusCode::BadInternalError, new DateTimeImmutable(), new DateTimeImmutable(), ); expect($dv->getEncodingMask())->toBe(0x0F); }); it('returns timestamps', function () { $src = new DateTimeImmutable('2024-01-01 00:00:00'); $srv = new DateTimeImmutable('2024-01-01 00:00:01'); $dv = new DataValue(null, 0, $src, $srv); expect($dv->getSourceTimestamp())->toBe($src); expect($dv->getServerTimestamp())->toBe($srv); }); }); describe('UserTokenPolicy', function () { it('returns all properties', function () { $policy = new UserTokenPolicy('anon', 0, null, null, null); expect($policy->getPolicyId())->toBe('anon'); expect($policy->getTokenType())->toBe(0); expect($policy->getIssuedTokenType())->toBeNull(); expect($policy->getIssuerEndpointUrl())->toBeNull(); expect($policy->getSecurityPolicyUri())->toBeNull(); }); it('returns all properties with values', function () { $policy = new UserTokenPolicy( 'username_policy', 1, 'urn:token:type', 'opc.tcp://issuer:4840', 'http://opcfoundation.org/UA/SecurityPolicy#Basic256Sha256', ); expect($policy->getPolicyId())->toBe('username_policy'); expect($policy->getTokenType())->toBe(1); expect($policy->getIssuedTokenType())->toBe('urn:token:type'); expect($policy->getIssuerEndpointUrl())->toBe('opc.tcp://issuer:4840'); expect($policy->getSecurityPolicyUri())->toBe('http://opcfoundation.org/UA/SecurityPolicy#Basic256Sha256'); }); }); describe('EndpointDescription', function () { it('returns all properties', function () { $token = new UserTokenPolicy('anon', 0, null, null, null); $ep = new EndpointDescription( 'opc.tcp://localhost:4840', 'cert-bytes', 1, 'http://opcfoundation.org/UA/SecurityPolicy#None', [$token], 'http://opcfoundation.org/UA-Profile/Transport/uatcp-uasc-uabinary', 0, ); expect($ep->getEndpointUrl())->toBe('opc.tcp://localhost:4840'); expect($ep->getServerCertificate())->toBe('cert-bytes'); expect($ep->getSecurityMode())->toBe(1); expect($ep->getSecurityPolicyUri())->toBe('http://opcfoundation.org/UA/SecurityPolicy#None'); expect($ep->getUserIdentityTokens())->toHaveCount(1); expect($ep->getTransportProfileUri())->toBe('http://opcfoundation.org/UA-Profile/Transport/uatcp-uasc-uabinary'); expect($ep->getSecurityLevel())->toBe(0); }); it('handles null server certificate', function () { $ep = new EndpointDescription('url', null, 1, 'policy', [], 'transport', 0); expect($ep->getServerCertificate())->toBeNull(); }); }); describe('ReferenceDescription', function () { it('returns all properties', function () { $refTypeId = NodeId::numeric(0, 35); $nodeId = NodeId::numeric(1, 1000); $browseName = new QualifiedName(1, 'TestNode'); $displayName = new LocalizedText('en', 'Test Node'); $typeDef = NodeId::numeric(0, 61); $ref = new ReferenceDescription( $refTypeId, true, $nodeId, $browseName, $displayName, NodeClass::Variable, $typeDef, ); expect($ref->getReferenceTypeId())->toBe($refTypeId); expect($ref->isForward())->toBeTrue(); expect($ref->getNodeId())->toBe($nodeId); expect($ref->getBrowseName())->toBe($browseName); expect($ref->getDisplayName())->toBe($displayName); expect($ref->getNodeClass())->toBe(NodeClass::Variable); expect($ref->getTypeDefinition())->toBe($typeDef); }); it('handles null type definition', function () { $ref = new ReferenceDescription( NodeId::numeric(0, 35), false, NodeId::numeric(0, 1), new QualifiedName(0, 'X'), new LocalizedText(null, 'X'), NodeClass::Object, ); expect($ref->getTypeDefinition())->toBeNull(); expect($ref->isForward())->toBeFalse(); }); }); describe('NodeId', function () { it('creates guid NodeId', function () { $node = NodeId::guid(1, '12345678-1234-1234-1234-123456789abc'); expect($node->isGuid())->toBeTrue(); expect($node->isNumeric())->toBeFalse(); expect($node->isString())->toBeFalse(); expect($node->isOpaque())->toBeFalse(); expect($node->getType())->toBe(NodeId::TYPE_GUID); expect($node->getEncodingByte())->toBe(0x04); }); it('creates opaque NodeId', function () { $node = NodeId::opaque(2, 'deadbeef'); expect($node->isOpaque())->toBeTrue(); expect($node->getType())->toBe(NodeId::TYPE_OPAQUE); expect($node->getEncodingByte())->toBe(0x05); }); it('encoding byte for large numeric uses full encoding', function () { // ns > 255 forces Numeric encoding $node = NodeId::numeric(256, 1); expect($node->getEncodingByte())->toBe(0x02); // id > 65535 forces Numeric encoding $node = NodeId::numeric(0, 70000); expect($node->getEncodingByte())->toBe(0x02); }); }); describe('Variant', function () { it('stores type and value', function () { $v = new Variant(BuiltinType::String, 'hello'); expect($v->getType())->toBe(BuiltinType::String); expect($v->getValue())->toBe('hello'); }); it('stores array values', function () { $v = new Variant(BuiltinType::Int32, [1, 2, 3]); expect($v->getValue())->toBe([1, 2, 3]); }); }); describe('LocalizedText', function () { it('toString returns empty string when text is null', function () { $lt = new LocalizedText('en', null); expect((string) $lt)->toBe(''); }); it('encoding mask with only locale', function () { $lt = new LocalizedText('en', null); expect($lt->getEncodingMask())->toBe(0x01); }); it('encoding mask with neither', function () { $lt = new LocalizedText(null, null); expect($lt->getEncodingMask())->toBe(0x00); }); });