code: /*
   * Copyright (c) 2019 the Eclipse Milo Authors
   *
   * This program and the accompanying materials are made
   * available under the terms of the Eclipse Public License 2.0
   * which is available at https://www.eclipse.org/legal/epl-2.0/
   *
   * SPDX-License-Identifier: EPL-2.0
   */
  
  package org.eclipse.milo.opcua.sdk.server.util;
  
  import java.util.function.Consumer;
  
  import org.eclipse.milo.opcua.sdk.core.AccessLevel;
  import org.eclipse.milo.opcua.sdk.core.ValueRanks;
  import org.eclipse.milo.opcua.sdk.server.OpcUaServer;
  import org.eclipse.milo.opcua.sdk.server.nodes.AttributeContext;
  import org.eclipse.milo.opcua.sdk.server.nodes.UaVariableNode;
  import org.eclipse.milo.opcua.stack.core.AttributeId;
  import org.eclipse.milo.opcua.stack.core.Identifiers;
  import org.eclipse.milo.opcua.stack.core.StatusCodes;
  import org.eclipse.milo.opcua.stack.core.UaException;
  import org.eclipse.milo.opcua.stack.core.types.builtin.ByteString;
  import org.eclipse.milo.opcua.stack.core.types.builtin.DataValue;
  import org.eclipse.milo.opcua.stack.core.types.builtin.LocalizedText;
  import org.eclipse.milo.opcua.stack.core.types.builtin.NodeId;
  import org.eclipse.milo.opcua.stack.core.types.builtin.QualifiedName;
  import org.eclipse.milo.opcua.stack.core.types.builtin.Variant;
  import org.eclipse.milo.opcua.stack.core.types.builtin.unsigned.UByte;
  import org.eclipse.milo.opcua.stack.core.types.builtin.unsigned.UInteger;
  import org.mockito.Mockito;
  import org.testng.Assert;
  import org.testng.annotations.Test;
  
  import static org.eclipse.milo.opcua.stack.core.types.builtin.unsigned.Unsigned.uint;
  
  public class AttributeWriterTest {
  
      @Test
      public void testVariantToVariant() throws UaException {
          testWriteConversion(new Variant("String"), null, null);
      }
  
      @Test
      public void testStringToString() throws UaException {
          testWriteConversion(new Variant("String"), Identifiers.String, null);
      }
  
      @Test
      public void testStringToDouble() throws UaException {
          expectFailure(StatusCodes.Bad_TypeMismatch, () -> testWriteConversion(new Variant("String"), Identifiers.Double, null));
      }
  
      @Test
      public void testByteStringToUByteArray() throws UaException {
          testWriteConversion(new Variant(ByteString.of("foo".getBytes())), Identifiers.Byte, node -> {
              node.setValueRank(ValueRanks.OneDimension);
              node.setArrayDimensions(new UInteger[]{uint(0)});
          });
      }
  
      public interface UaOperation {
          void run() throws UaException;
      }
  
      private static void expectFailure(long code, UaOperation operation) {
          try {
              operation.run();
              Assert.fail("Operation is expected to fail with code: " + code);
          } catch (UaException e) {
              Assert.assertEquals(e.getStatusCode().getValue(), code, "Status code does not match");
          }
      }
  
      private void testWriteConversion(
          Variant value,
          NodeId dataType,
          Consumer<UaVariableNode> nodeCustomizer) throws UaException {
  
          testWriteConversion(new DataValue(value), dataType, nodeCustomizer);
  
      }
  
      private void testWriteConversion(
          DataValue value,
          NodeId dataType,
          Consumer<UaVariableNode> nodeCustomizer) throws UaException {
  
          final UaVariableNode varNode = createMockNode("test", node -> {
              UByte accessLevel = AccessLevel.toValue(AccessLevel.READ_WRITE);
              node.setAccessLevel(accessLevel);
              node.setUserAccessLevel(accessLevel);
              if (nodeCustomizer != null) {
                  nodeCustomizer.accept(node);
              }
          });
  
          if (dataType != null) {
              varNode.setDataType(dataType);
          }
  
          OpcUaServer server = Mockito.mock(OpcUaServer.class);
  
          AttributeWriter.writeAttribute(
              new AttributeContext(server, null),
              varNode,
              AttributeId.Value,
              value,
              null
          );
      }
  
      private UaVariableNode createMockNode(
          String id,
          Consumer<UaVariableNode> nodeCustomizer) {
  
          final NodeId nodeId = new NodeId(0, id);
  
          final QualifiedName browseName = new QualifiedName(0, id);
          final LocalizedText displayName = LocalizedText.english(id);
  
          final UaVariableNode node = new UaVariableNode(
              null, nodeId, browseName, displayName);
  
          if (nodeCustomizer != null) {
              nodeCustomizer.accept(node);
          }
  
          return node;
      }
  
  }
  