text: # SPDX-License-Identifier: Apache-2.0
  
  from __future__ import absolute_import
  from __future__ import division
  from __future__ import print_function
  from __future__ import unicode_literals
  
  from onnx import checker, helper, ModelProto, TensorProto, GraphProto, NodeProto, OperatorSetIdProto
  from typing import Sequence, Text, Tuple, List, Callable
  from onnx import numpy_helper
  
  import numpy as np  # type: ignore
  import struct
  
  import onnx.version_converter
  import unittest
  
  
  class TestVersionConverter(unittest.TestCase):
  
      def _converted(
              self,
              graph: GraphProto,
              initial_version: OperatorSetIdProto,
              target_version: int
      ) -> ModelProto:
          orig_model = helper.make_model(graph, producer_name='onnx-test', opset_imports=[initial_version])
          # print(type(orig_model))
          converted_model = onnx.version_converter.convert_version(orig_model,
                  target_version)
          checker.check_model(converted_model)
          return converted_model
  
      # Test 1: Backwards Incompatible Conversion: Reshape: 8 -> 2
      def test_backwards_incompatible(self) -> None:
          def test() -> None:
              nodes = [helper.make_node('Add', ["W", "Z"], ["shape"]),
                          helper.make_node('Reshape', ["X", "shape"], ["A"]),
                          helper.make_node('Add', ["A", "W"], ["Y"])]
              graph = helper.make_graph(
                  nodes,
                  "test",
                  [helper.make_tensor_value_info("X", TensorProto.FLOAT, (5,)),
                      helper.make_tensor_value_info("W", TensorProto.FLOAT, (1,)),
                      helper.make_tensor_value_info("Z", TensorProto.FLOAT, (1,))],
                  [helper.make_tensor_value_info("Y", TensorProto.FLOAT, (5,))])
              self._converted(graph, helper.make_operatorsetid("", 8), 2)
          self.assertRaises(RuntimeError, test)
  
      # Test 2: Backwards Compatible Conversion (No Adaptations): Add: 3 -> 2
      def test_backwards_compatible(self) -> None:
          nodes = [helper.make_node('Add', ["X1", "X2"], ["Y"])]
          graph = helper.make_graph(
              nodes,
              "test",
              [helper.make_tensor_value_info("X1", TensorProto.FLOAT, (5,)),
                  helper.make_tensor_value_info("X2", TensorProto.FLOAT, (5,))],
              [helper.make_tensor_value_info("Y", TensorProto.FLOAT, (5,))])
          converted_model = self._converted(graph, helper.make_operatorsetid(
              "", 3), 2)
          # Assert equality of graph and converted_model
          assert converted_model.graph.node[0].op_type == "Add"
          assert converted_model.opset_import[0].version == 2
  
      # Test 3: Non-Existent Op Conversion: Cos: 8 -> 6
      def test_non_existent_op(self) -> None:
          def test() -> None:
              nodes = [helper.make_node('Cos', ["X"], ["Y"])]
              graph = helper.make_graph(
                  nodes,
                  "test",
                  [helper.make_tensor_value_info("X", TensorProto.FLOAT, (5,))],
                  [helper.make_tensor_value_info("Y", TensorProto.FLOAT, (5,))])
              self._converted(graph, helper.make_operatorsetid("", 8), 6)
          self.assertRaises(RuntimeError, test)
  
      # Test Add Adapter: 8 -> 5
      def test_add_8_5(self) -> None:
          nodes = [helper.make_node('Add', ["X1", "X2"], ["Y"])]
          graph = helper.make_graph(
              nodes,
              "test",
              [helper.make_tensor_value_info("X1", TensorProto.FLOAT, (5,)),
                  helper.make_tensor_value_info("X2", TensorProto.FLOAT, (1,))],
              [helper.make_tensor_value_info("Y", TensorProto.FLOAT, (5,))])
          converted_model = self._converted(graph, helper.make_operatorsetid(
              "", 8), 5)
          # Assert equality of graph and converted_model
          assert converted_model.graph.node[0].op_type == "Add"
          assert converted_model.opset_import[0].version == 5
  
      # Test Add Adapter: 5 -> 8
      def test_add_5_8(self) -> None:
          nodes = [helper.make_node('Add', ["X1", "X2"], ["Y"])]
          graph = helper.make_graph(
              nodes,
              "test",
              [helper.make_tensor_value_info("X1", TensorProto.FLOAT, (5,)),
                  helper.make_tensor_value_info("X2", TensorProto.FLOAT, (1,))],
              [helper.make_tensor_value_info("Y", TensorProto.FLOAT, (5,))])
          converted_model = self._converted(graph, helper.make_operatorsetid(
              "", 5), 8)
          # Assert equality of graph and converted_model
          assert converted_model.graph.node[0].op_type == "Add"
          assert converted_model.opset_import[0].version == 8
  
      # Test Add Adapter: 5 -> 8, requiring insertion of an Unsqueeze node
      def test_add_5_8_with_unsqueeze(self) -> None:
          nodes = [helper.make_node('Add', ["X1", "X2"], ["Y"], axis=0, broadcast=1)]
          graph = helper.make_graph(
              nodes,
              "test",
              [helper.make_tensor_value_info("X1", TensorProto.FLOAT, (5, 2)),
                  helper.make_tensor_value_info("X2", TensorProto.FLOAT, (5,))],
              [helper.make_tensor_value_info("Y", TensorProto.FLOAT, (5,))])
          converted_model = self._converted(graph, helper.make_operatorsetid(
              "", 5), 8)
          # Assert equality of graph and converted_model
          assert converted_model.graph.node[0].op_type == "Unsqueeze"
          assert converted_model.graph.node[1].op_type == "Add"
          assert converted_model.opset_import[0].version == 8
  
      # Test Mul Adapter: 8 -> 5
      def test_mul_8_5(self) -> None:
          nodes = [helper.make_node('Mul', ["X1", "X2"], ["Y"])]
          graph = helper.make_graph(
              nodes,
              "test",
              [helper.make_tensor_value_info("X1", TensorProto.FLOAT, (5,)),
                  helper.make_tensor_value_info("X2", TensorProto.FLOAT, (1,))],
              [helper.make_tensor_value_info("Y", TensorProto.FLOAT, (5,))])
          converted_model = self._converted(graph, helper.make_operatorsetid(
              "", 8), 5)
          # Assert equality of graph and converted_model
          assert converted_model.graph.node[0].op_type == "Mul"
          assert converted_model.opset_import[0].version == 5
  
      # Test Mul Adapter: 5 -> 8
      def test_mul_5_8(self) -> None:
          nodes = [helper.make_node('Mul', ["X1", "X2"], ["Y"])]
          graph = helper.make_graph(
              nodes,
              "test",
              [helper.make_tensor_value_info("X1", TensorProto.FLOAT, (5,)),
                  helper.make_tensor_value_info("X2", TensorProto.FLOAT, (1,))],
              [helper.make_tensor_value_info("Y", TensorProto.FLOAT, (5,))])
          converted_model = self._converted(graph, helper.make_operatorsetid(
              "", 5), 8)
          # Assert equality of graph and converted_model
          assert converted_model.graph.node[0].op_type == "Mul"
          assert converted_model.opset_import[0].version == 8
  
      # Test Gemm Adapter: 1 -> 8
      def test_gemm_up(self) -> None:
          nodes = [helper.make_node('Gemm', ["A", "B", "C"], ["Y"])]
          graph = helper.make_graph(
              nodes,
              "test",
              [helper.make_tensor_value_info("A", TensorProto.FLOAT, (5, 5,)),
                  helper.make_tensor_value_info("B", TensorProto.FLOAT, (5, 5,)),
                  helper.make_tensor_value_info("C", TensorProto.FLOAT, (5, 5,))],
              [helper.make_tensor_value_info("Y", TensorProto.FLOAT, (5, 5,))])
          converted_model = self._converted(graph, helper.make_operatorsetid(
              "", 1), 8)
          # Assert equality of graph and converted_model
          assert converted_model.graph.node[0].op_type == "Gemm"
          assert converted_model.opset_import[0].version == 8
  
      # Test Gemm Adapter: 8 -> 1
      def test_gemm_down(self) -> None:
          nodes = [helper.make_node('Gemm', ["A", "B", "C"], ["Y"])]
          graph = helper.make_graph(
              nodes,
              "test",
              [helper.make_tensor_value_info("A", TensorProto.FLOAT, (5, 5,)),
                  helper.make_tensor_value_info("B", TensorProto.FLOAT, (5, 5,)),
                  helper.make_tensor_value_info("C", TensorProto.FLOAT, (5, 5,))],
              [helper.make_tensor_value_info("Y", TensorProto.FLOAT, (5, 5,))])
          converted_model = self._converted(graph, helper.make_operatorsetid(
              "", 8), 1)
          # Assert equality of graph and converted_model
          assert converted_model.graph.node[0].op_type == "Gemm"
          assert converted_model.opset_import[0].version == 1
  
      # Test Relu Adapter: 5 -> 7
      def test_relu_5_7(self) -> None:
          nodes = [helper.make_node('Relu', ["X"], ["Y"])]
          graph = helper.make_graph(
              nodes,
              "test",
              [helper.make_tensor_value_info("X", TensorProto.FLOAT, (5,))],
              [helper.make_tensor_value_info("Y", TensorProto.FLOAT, (5,))])
          converted_model = self._converted(graph, helper.make_operatorsetid(
              "", 5), 7)
          # Assert equality of graph and converted_model
          assert converted_model.graph.node[0].op_type == "Relu"
          assert converted_model.opset_import[0].version == 7
  
      # Test Relu Adapter: 7 -> 5
      def test_relu_7_5(self) -> None:
          nodes = [helper.make_node('Relu', ["X"], ["Y"])]
          graph = helper.make_graph(
              nodes,
              "test",
              [helper.make_tensor_value_info("X", TensorProto.FLOAT, (5,))],
              [helper.make_tensor_value_info("Y", TensorProto.FLOAT, (5,))])
          converted_model = self._converted(graph, helper.make_operatorsetid(
              "", 7), 5)
          # Assert equality of graph and converted_model
          assert converted_model.graph.node[0].op_type == "Relu"
          assert converted_model.opset_import[0].version == 5
  
      # Test BatchNormalization Adapter: 8 -> 5
      def test_batch_normalization_8_5(self) -> None:
          nodes = [helper.make_node('BatchNormalization', ["X", "scale", "B",
              "mean", "var"], ["Y"])]
          graph = helper.make_graph(
              nodes,
              "test",
              [helper.make_tensor_value_info("X", TensorProto.FLOAT, (5,)),
                  helper.make_tensor_value_info("scale", TensorProto.FLOAT, (1,)),
                  helper.make_tensor_value_info("B", TensorProto.FLOAT, (1,)),
                  helper.make_tensor_value_info("mean", TensorProto.FLOAT, (1,)),
                  helper.make_tensor_value_info("var", TensorProto.FLOAT, (1,))],
              [helper.make_tensor_value_info("Y", TensorProto.FLOAT, (5,))])
          converted_model = self._converted(graph, helper.make_operatorsetid(
              "", 8), 5)
          # Assert equality of graph and converted_model
          assert converted_model.graph.node[0].op_type == "BatchNormalization"
          assert converted_model.opset_import[0].version == 5
  
      # Test BatchNormalization Adapter: 5 -> 8
      def test_batch_normalization_5_8(self) -> None:
          nodes = [helper.make_node('BatchNormalization', ["X", "scale", "B",
              "mean", "var"], ["Y"])]
          graph = helper.make_graph(
              nodes,
              "test",
              [helper.make_tensor_value_info("X", TensorProto.FLOAT, (5,)),
                  helper.make_tensor_value_info("scale", TensorProto.FLOAT, (1,)),
                  helper.make_tensor_value_info("B", TensorProto.FLOAT, (1,)),
                  helper.make_tensor_value_info("mean", TensorProto.FLOAT, (1,)),
                  helper.make_tensor_value_info("var", TensorProto.FLOAT, (1,))],
              [helper.make_tensor_value_info("Y", TensorProto.FLOAT, (5,))])
          converted_model = self._converted(graph, helper.make_operatorsetid(
              "", 5), 8)
          # Assert equality of graph and converted_model
          assert converted_model.graph.node[0].op_type == "BatchNormalization"
          assert converted_model.opset_import[0].version == 8
  
      # Test Concat Adapter: 3 -> 5
      def test_concat_3_5(self) -> None:
          nodes = [helper.make_node('Concat', ["X1", "X2", "X3",
              "X4", "X5"], ["Y"])]
          graph = helper.make_graph(
              nodes,
              "test",
              [helper.make_tensor_value_info("X1", TensorProto.FLOAT, (1,)),
                  helper.make_tensor_value_info("X2", TensorProto.FLOAT, (1,)),
                  helper.make_tensor_value_info("X3", TensorProto.FLOAT, (1,)),
                  helper.make_tensor_value_info("X4", TensorProto.FLOAT, (1,)),
                  helper.make_tensor_value_info("X5", TensorProto.FLOAT, (1,))],
              [helper.make_tensor_value_info("Y", TensorProto.FLOAT, (5,))])
          converted_model = self._converted(graph, helper.make_operatorsetid(
              "", 3), 5)
          # Assert equality of graph and converted_model
          assert converted_model.graph.node[0].op_type == "Concat"
          assert converted_model.opset_import[0].version == 5
  
      # Test Concat Adapter: 5 -> 3
      def test_concat_5_3(self) -> None:
          nodes = [helper.make_node('Concat', ["X1", "X2", "X3",
              "X4", "X5"], ["Y"], axis=0)]
          graph = helper.make_graph(
              nodes,
              "test",
              [helper.make_tensor_value_info("X1", TensorProto.FLOAT, (1,)),
                  helper.make_tensor_value_info("X2", TensorProto.FLOAT, (1,)),
                  helper.make_tensor_value_info("X3", TensorProto.FLOAT, (1,)),
                  helper.make_tensor_value_info("X4", TensorProto.FLOAT, (1,)),
                  helper.make_tensor_value_info("X5", TensorProto.FLOAT, (1,))],
              [helper.make_tensor_value_info("Y", TensorProto.FLOAT, (5,))])
          converted_model = self._converted(graph, helper.make_operatorsetid(
              "", 5), 3)
          # Assert equality of graph and converted_model
          assert converted_model.graph.node[0].op_type == "Concat"
          assert converted_model.opset_import[0].version == 3
  
      # Test Reshape Adapter: 6 -> 4
      def test_reshape_6_4(self) -> None:
          nodes = [helper.make_node('Constant', [], ["shape"],
                      value=helper.make_tensor("", TensorProto.INT64, [1],
                          [5])),
                      helper.make_node('Reshape', ["X", "shape"], ["Y"])]
          graph = helper.make_graph(
              nodes,
              "test",
              [helper.make_tensor_value_info("X", TensorProto.FLOAT, (5,))],
              [helper.make_tensor_value_info("Y", TensorProto.FLOAT, (5,))])
          converted_model = self._converted(graph, helper.make_operatorsetid(
              "", 6), 4)
          # Assert equality of graph and converted_model
          assert converted_model.graph.node[0].op_type == "Reshape"
          assert converted_model.opset_import[0].version == 4
  
      # Test Reshape Adapter: 4 -> 6
      def test_reshape_4_6(self) -> None:
          nodes = [helper.make_node('Reshape', ["X"], ["Y"], shape=[5])]
          graph = helper.make_graph(
              nodes,
              "test",
              [helper.make_tensor_value_info("X", TensorProto.FLOAT, (5,))],
              [helper.make_tensor_value_info("Y", TensorProto.FLOAT, (5,))])
          converted_model = self._converted(graph, helper.make_operatorsetid(
              "", 4), 6)
          # Assert equality of graph and converted_model
          assert converted_model.graph.node[0].op_type == "Constant"
          assert converted_model.graph.node[1].op_type == "Reshape"
          assert converted_model.opset_import[0].version == 6
  
      # Test Sum Adapter: 7 -> 8
      def test_sum_7_8(self) -> None:
          nodes = [helper.make_node('Sum', ["data_0", "data_1", "data_2",
              "data_3", "data_4"], ["sum"])]
          graph = helper.make_graph(
              nodes,
              "test",
              [helper.make_tensor_value_info("data_0", TensorProto.FLOAT, (5,)),
                  helper.make_tensor_value_info("data_1", TensorProto.FLOAT, (5,)),
                  helper.make_tensor_value_info("data_2", TensorProto.FLOAT, (5,)),
                  helper.make_tensor_value_info("data_3", TensorProto.FLOAT, (5,)),
                  helper.make_tensor_value_info("data_4", TensorProto.FLOAT, (5,))],
              [helper.make_tensor_value_info("sum", TensorProto.FLOAT, (5,))])
          converted_model = self._converted(graph, helper.make_operatorsetid(
              "", 7), 8)
          # Assert equality of graph and converted_model
          assert converted_model.graph.node[0].op_type == "Sum"
          assert converted_model.opset_import[0].version == 8
  
      # Test Sum Adapter: 5 -> 8
      def test_sum_5_8(self) -> None:
          nodes = [helper.make_node('Sum', ["data_0", "data_1", "data_2",
              "data_3", "data_4"], ["sum"])]
          graph = helper.make_graph(
              nodes,
              "test",
              [helper.make_tensor_value_info("data_0", TensorProto.FLOAT, (5,)),
                  helper.make_tensor_value_info("data_1", TensorProto.FLOAT, (5,)),
                  helper.make_tensor_value_info("data_2", TensorProto.FLOAT, (5,)),
                  helper.make_tensor_value_info("data_3", TensorProto.FLOAT, (5,)),
                  helper.make_tensor_value_info("data_4", TensorProto.FLOAT, (5,))],
              [helper.make_tensor_value_info("sum", TensorProto.FLOAT, (5,))])
          converted_model = self._converted(graph, helper.make_operatorsetid(
              "", 5), 7)
          # Assert equality of graph and converted_model
          assert converted_model.graph.node[0].op_type == "Sum"
          assert converted_model.opset_import[0].version == 7
  
      # Test Sum Adapter: 8 -> 5
      def test_sum_8_5(self) -> None:
          nodes = [helper.make_node('Sum', ["data_0", "data_1", "data_2",
              "data_3", "data_4"], ["sum"])]
          graph = helper.make_graph(
              nodes,
              "test",
              [helper.make_tensor_value_info("data_0", TensorProto.FLOAT, (5,)),
                  helper.make_tensor_value_info("data_1", TensorProto.FLOAT, (5,)),
                  helper.make_tensor_value_info("data_2", TensorProto.FLOAT, (5,)),
                  helper.make_tensor_value_info("data_3", TensorProto.FLOAT, (5,)),
                  helper.make_tensor_value_info("data_4", TensorProto.FLOAT, (5,))],
              [helper.make_tensor_value_info("sum", TensorProto.FLOAT, (5,))])
          converted_model = self._converted(graph, helper.make_operatorsetid(
              "", 8), 5)
          # Assert equality of graph and converted_model
          assert converted_model.graph.node[0].op_type == "Sum"
          assert converted_model.opset_import[0].version == 5
  
      # Test AveragePool Adapter: 1 -> 8
      def test_averagepool_up(self) -> None:
          nodes = [helper.make_node('AveragePool', ["X"], ["Y"], kernel_shape=[1, 1])]
          graph = helper.make_graph(
              nodes,
              "test",
              [helper.make_tensor_value_info("X", TensorProto.FLOAT, (5, 5, 5, 5))],
              [helper.make_tensor_value_info("Y", TensorProto.FLOAT, (5, 5, 5, 5))])
          converted_model = self._converted(graph, helper.make_operatorsetid(
              "", 1), 8)
          # Assert equality of graph and converted_model
          assert converted_model.graph.node[0].op_type == "AveragePool"
          assert converted_model.opset_import[0].version == 8
  
      # Test AveragePool Adapter: 8 -> 1
      def test_averagepool_down(self) -> None:
          nodes = [helper.make_node('AveragePool', ["X"], ["Y"], kernel_shape=[1, 1])]
          graph = helper.make_graph(
              nodes,
              "test",
              [helper.make_tensor_value_info("X", TensorProto.FLOAT, (5, 5, 5, 5))],
              [helper.make_tensor_value_info("Y", TensorProto.FLOAT, (5, 5, 5, 5))])
          converted_model = self._converted(graph, helper.make_operatorsetid(
              "", 8), 1)
          # Assert equality of graph and converted_model
          assert converted_model.graph.node[0].op_type == "AveragePool"
          assert converted_model.opset_import[0].version == 1
  
      # Test Dropout Adapter: 1 -> 8
      def test_dropout_up(self) -> None:
          nodes = [helper.make_node('Dropout', ["data"], ["output"], is_test=1)]
          graph = helper.make_graph(
              nodes,
              "test",
              [helper.make_tensor_value_info("data", TensorProto.FLOAT, (5, 5,))],
              [helper.make_tensor_value_info("output", TensorProto.FLOAT, (5, 5,))])
          converted_model = self._converted(graph, helper.make_operatorsetid(
              "", 1), 8)
          # Assert equality of graph and converted_model
          assert converted_model.graph.node[0].op_type == "Dropout"
          assert converted_model.opset_import[0].version == 8
  
      # Test Dropout Adapter: 8 -> 1
      def test_dropout_down(self) -> None:
          nodes = [helper.make_node('Dropout', ["data"], ["output"])]
          graph = helper.make_graph(
              nodes,
              "test",
              [helper.make_tensor_value_info("data", TensorProto.FLOAT, (5, 5,))],
              [helper.make_tensor_value_info("output", TensorProto.FLOAT, (5, 5,))])
          converted_model = self._converted(graph, helper.make_operatorsetid(
              "", 8), 1)
          # Assert equality of graph and converted_model
          assert converted_model.graph.node[0].op_type == "Dropout"
          assert converted_model.opset_import[0].version == 1
  
      # Test Max Adapter: 7 -> 8
      def test_max_7_8(self) -> None:
          from_opset = 7
          to_opset = 8
          data_type = TensorProto.FLOAT
          data_shape = (2, 3, 4)
  
          nodes = [onnx.helper.make_node(
              "Max",
              inputs=["X"],
              outputs=["Y"]
          )]
  
          graph = helper.make_graph(
              nodes,
              "test_max",
              [onnx.helper.make_tensor_value_info("X", data_type, data_shape)],
              [onnx.helper.make_tensor_value_info("Y", data_type, data_shape)])
  
          converted_model = self._converted(graph, helper.make_operatorsetid("", from_opset), to_opset)
  
          assert converted_model.graph.node[0].op_type == "Max"
          assert converted_model.graph.output[0].type.tensor_type.elem_type == data_type
          assert converted_model.opset_import[0].version == to_opset
  
      # Test Min Adapter: 7 -> 8
      def test_min_7_8(self) -> None:
          from_opset = 7
          to_opset = 8
          data_type = TensorProto.FLOAT
          data_shape = (2, 3, 4)
  
          nodes = [onnx.helper.make_node(
              "Min",
              inputs=["X"],
              outputs=["Y"]
          )]
  
          graph = helper.make_graph(
              nodes,
              "test_min",
              [onnx.helper.make_tensor_value_info("X", data_type, data_shape)],
              [onnx.helper.make_tensor_value_info("Y", data_type, data_shape)])
  
          converted_model = self._converted(graph, helper.make_operatorsetid("", from_opset), to_opset)
  
          assert converted_model.graph.node[0].op_type == "Min"
          assert converted_model.graph.output[0].type.tensor_type.elem_type == data_type
          assert converted_model.opset_import[0].version == to_opset
  
      # Test Mean Adapter: 7 -> 8
      def test_mean_7_8(self) -> None:
          from_opset = 7
          to_opset = 8
          data_type = TensorProto.FLOAT
          data_shape = (3,)
  
          nodes = [onnx.helper.make_node(
              "Mean",
              inputs=["X"],
              outputs=["Y"]
          )]
  
          graph = helper.make_graph(
              nodes,
              "test_mean",
              [onnx.helper.make_tensor_value_info("X", data_type, data_shape)],
              [onnx.helper.make_tensor_value_info("Y", data_type, data_shape)])
  
          converted_model = self._converted(graph, helper.make_operatorsetid("", from_opset), to_opset)
  
          assert converted_model.graph.node[0].op_type == "Mean"
          assert converted_model.graph.output[0].type.tensor_type.elem_type == data_type
          assert converted_model.opset_import[0].version == to_opset
  
      # Test MaxPool Adapter: 1 -> 8
      def test_maxpool_up(self) -> None:
          nodes = [helper.make_node('MaxPool', ["X"], ["Y"], kernel_shape=[1, 1])]
          graph = helper.make_graph(
              nodes,
              "test",
              [helper.make_tensor_value_info("X", TensorProto.FLOAT, (5, 5, 5, 5))],
              [helper.make_tensor_value_info("Y", TensorProto.FLOAT, (5, 5, 5, 5))])
          converted_model = self._converted(graph, helper.make_operatorsetid(
              "", 1), 8)
          # Assert equality of graph and converted_model
          assert converted_model.graph.node[0].op_type == "MaxPool"
          assert converted_model.opset_import[0].version == 8
  
      # Test Upsample Adapter: 6 -> 7
      def test_upsample_6_7(self) -> None:
          from_opset = 6
          to_opset = 7
          data_type = TensorProto.FLOAT
  
          nodes = [onnx.helper.make_node(
              "Upsample",
              inputs=["X"],
              outputs=["Y"],
              mode="nearest",
              width_scale=3.0,
              height_scale=2.0
          )]
  
          graph = helper.make_graph(
              nodes,
              "test_upsample_6_7",
              [onnx.helper.make_tensor_value_info("X", data_type, [1, 1, 2, 2])],
              [onnx.helper.make_tensor_value_info("Y", data_type, [1, 1, 4, 6])]
          )
  
          converted_model = self._converted(graph, helper.make_operatorsetid("", from_opset), to_opset)
  
          assert len(converted_model.graph.node) == 1
          assert converted_model.graph.node[0].op_type == "Upsample"
          attribute_names = [attr.name for attr in converted_model.graph.node[0].attribute]
          assert 'scales' in attribute_names
          assert 'width_scale' not in attribute_names
          assert 'height_scale' not in attribute_names
          assert converted_model.opset_import[0].version == to_opset
  
      # Test MaxPool Adapter: 8 -> 1
      def test_maxpool_down(self) -> None:
          nodes = [helper.make_node('MaxPool', ["X"], ["Y"], kernel_shape=[1, 1])]
          graph = helper.make_graph(
              nodes,
              "test",
              [helper.make_tensor_value_info("X", TensorProto.FLOAT, (5, 5, 5, 5))],
              [helper.make_tensor_value_info("Y", TensorProto.FLOAT, (5, 5, 5, 5))])
          converted_model = self._converted(graph, helper.make_operatorsetid(
              "", 8), 1)
          # Assert equality of graph and converted_model
          assert converted_model.graph.node[0].op_type == "MaxPool"
          assert converted_model.opset_import[0].version == 1
  
      # Test BatchNormalization Adapter: 8 -> 9
      def test_batch_normalization_8_9(self) -> None:
          from_opset = 8
          to_opset = 9
          data_type = TensorProto.FLOAT
  
          nodes = [helper.make_node(
              'BatchNormalization',
              inputs=["x", "s", "bias", "mean", "var"],
              outputs=["y"]
          )]
  
          input_shape = (1, 2, 1, 3)
          x = helper.make_tensor_value_info("x", data_type, input_shape)
          scale = helper.make_tensor_value_info("s", data_type, [input_shape[1]])
          B = helper.make_tensor_value_info("bias", data_type, [input_shape[1]])
          mean = helper.make_tensor_value_info("mean", data_type, [input_shape[1]])
          var = helper.make_tensor_value_info("var", data_type, [input_shape[1]])
          y = helper.make_tensor_value_info("y", data_type, input_shape)
  
          graph = helper.make_graph(
              nodes,
              "test_batchnormalization_8_9",
              [x, scale, B, mean, var],
              [y]
          )
  
          converted_model = self._converted(graph, helper.make_operatorsetid("", from_opset), to_opset)
  
          assert converted_model.graph.node[0].op_type == "BatchNormalization"
          assert converted_model.opset_import[0].version == to_opset
  
      # Test BatchNormalization Adapter: 9 -> 8
      def test_batchnormalization_9_8(self) -> None:
          from_opset = 9
          to_opset = 8
          data_type = TensorProto.FLOAT
  
          nodes = [onnx.helper.make_node(
              'BatchNormalization',
              inputs=['X', 'scale', 'B', 'mean', 'var'],
              outputs=['Y'],
          )]
  
          input_shape = (2, 3, 4, 5)
          x = onnx.helper.make_tensor_value_info("X", data_type, input_shape)
          scale = onnx.helper.make_tensor_value_info("scale", data_type, [input_shape[1]])
          B = onnx.helper.make_tensor_value_info("B", data_type, [input_shape[1]])
          mean = onnx.helper.make_tensor_value_info("mean", data_type, [input_shape[1]])
          var = onnx.helper.make_tensor_value_info("var", data_type, [input_shape[1]])
          y = onnx.helper.make_tensor_value_info("Y", data_type, input_shape)
  
          graph = onnx.helper.make_graph(
              nodes, "test_batchnormalization", [x, scale, B, mean, var], [y]
          )
  
          converted_model = self._converted(graph, helper.make_operatorsetid("", from_opset), to_opset)
  
          assert converted_model.graph.node[0].op_type == "BatchNormalization"
          assert converted_model.opset_import[0].version == to_opset
  
      # Test Constant Adapter: 8 -> 9
      def test_constant_8_9(self) -> None:
          from_opset = 8
          to_opset = 9
          data_type = TensorProto.FLOAT
  
          output_shape = [2, 3, 4]
          output_value = np.arange(24)
  
          nodes = [helper.make_node(
              "Constant",
              inputs=[],
              outputs=["Y"],
              value=helper.make_tensor("", data_type, output_shape, output_value))]
  
          graph = helper.make_graph(
              nodes,
              "test_constant",
              [],
              [onnx.helper.make_tensor_value_info("Y", data_type, output_shape)])
  
          converted_model = self._converted(graph, helper.make_operatorsetid("", from_opset), to_opset)
  
          assert converted_model.graph.node[0].op_type == "Constant"
          assert converted_model.graph.output[0].type.tensor_type.elem_type == data_type
          assert converted_model.opset_import[0].version == to_opset
  
      # Test Constant Adapter: 9 -> 8
      def test_constant_9_8(self) -> None:
          from_opset = 9
          to_opset = 8
          data_type = TensorProto.UINT64
  
          output_shape = [2, 3, 4]
          output_value = np.arange(24)
  
          nodes = [helper.make_node(
              "Constant",
              inputs=[],
              outputs=["Y"],
              value=helper.make_tensor("", data_type, output_shape, output_value))]
  
          graph = helper.make_graph(
              nodes,
              "test_constant",
              [],
              [onnx.helper.make_tensor_value_info("Y", data_type, output_shape)])
  
          converted_model = self._converted(graph, helper.make_operatorsetid("", from_opset), to_opset)
  
          assert converted_model.graph.node[0].op_type == "Constant"
          assert converted_model.graph.output[0].type.tensor_type.elem_type == data_type
          assert converted_model.opset_import[0].version == to_opset
  
      # Test Flatten Adapter: 8 -> 9
      def test_flatten_8_9(self) -> None:
          from_opset = 8
          to_opset = 9
          data_type = TensorProto.FLOAT
  
          nodes = [onnx.helper.make_node(
              "Flatten",
              inputs=["X"],
              outputs=["Y"],
              axis=1
          )]
  
          graph = helper.make_graph(
              nodes,
              "test_flatten",
              [onnx.helper.make_tensor_value_info("X", data_type, [2, 3, 4])],
              [onnx.helper.make_tensor_value_info("Y", data_type, [2, 12])])
  
          converted_model = self._converted(graph, helper.make_operatorsetid("", from_opset), to_opset)
  
          assert converted_model.graph.node[0].op_type == "Flatten"
          assert converted_model.graph.output[0].type.tensor_type.elem_type == data_type
          assert converted_model.opset_import[0].version == to_opset
  
      # Test Flatten Adapter: 9 -> 8
      def test_flatten_9_8(self) -> None:
          from_opset = 9
          to_opset = 8
          data_type = TensorProto.UINT64
  
          nodes = [onnx.helper.make_node(
              "Flatten",
              inputs=["X"],
              outputs=["Y"],
              axis=1
          )]
  
          graph = helper.make_graph(
              nodes,
              "test_flatten",
              [onnx.helper.make_tensor_value_info("X", data_type, [2, 3, 4])],
              [onnx.helper.make_tensor_value_info("Y", data_type, [2, 12])])
  
          converted_model = self._converted(graph, helper.make_operatorsetid("", from_opset), to_opset)
  
          assert converted_model.graph.node[1].op_type == "Flatten"
          assert converted_model.graph.output[0].type.tensor_type.elem_type == data_type
          assert converted_model.opset_import[0].version == to_opset
  
      # Test PRelu Adapter: 8 -> 9
      def test_prelu_8_9(self) -> None:
          from_opset = 8
          to_opset = 9
          data_type = TensorProto.FLOAT
  
          nodes = [onnx.helper.make_node(
              "PRelu",
              inputs=["X", "Slope"],
              outputs=["Y"]
          )]
  
          input_shape = [2, 3, 4]
          graph = helper.make_graph(
              nodes,
              "test_prelu",
              [onnx.helper.make_tensor_value_info("X", data_type, input_shape),
               onnx.helper.make_tensor_value_info("Slope", data_type, input_shape)],
              [onnx.helper.make_tensor_value_info("Y", data_type, input_shape)])
  
          converted_model = self._converted(graph, helper.make_operatorsetid("", from_opset), to_opset)
  
          assert converted_model.graph.node[0].op_type == "PRelu"
          assert converted_model.graph.output[0].type.tensor_type.elem_type == data_type
          assert converted_model.opset_import[0].version == to_opset
  
      # Test PRelu Adapter: 9 -> 8
      def test_prelu_9_8(self) -> None:
          from_opset = 9
          to_opset = 8
          data_type = TensorProto.UINT64
  
          nodes = [onnx.helper.make_node(
              "PRelu",
              inputs=["X", "Slope"],
              outputs=["Y"]
          )]
  
          input_shape = [2, 3, 4]
          graph = helper.make_graph(
              nodes,
              "test_prelu",
              [onnx.helper.make_tensor_value_info("X", data_type, input_shape),
               onnx.helper.make_tensor_value_info("Slope", data_type, input_shape)],
              [onnx.helper.make_tensor_value_info("Y", data_type, input_shape)])
  
          converted_model = self._converted(graph, helper.make_operatorsetid("", from_opset), to_opset)
  
          assert converted_model.graph.node[2].op_type == "PRelu"
          assert converted_model.graph.output[0].type.tensor_type.elem_type == data_type
          assert converted_model.opset_import[0].version == to_opset
  
      # Test Greater Adapter: 8 -> 9
      def test_greater_8_9(self) -> None:
          from_opset = 8
          to_opset = 9
          data_type = TensorProto.FLOAT
  
          nodes = [onnx.helper.make_node(
              "Greater",
              inputs=["X1", "X2"],
              outputs=["Y"]
          )]
  
          input_shape = [2, 3, 4]
          graph = helper.make_graph(
              nodes,
              "test_greater",
              [onnx.helper.make_tensor_value_info("X1", data_type, input_shape),
               onnx.helper.make_tensor_value_info("X2", data_type, input_shape)],
              [onnx.helper.make_tensor_value_info("Y", TensorProto.BOOL, input_shape)])
  
          converted_model = self._converted(graph, helper.make_operatorsetid("", from_opset), to_opset)
  
          assert converted_model.graph.node[0].op_type == "Greater"
          assert converted_model.graph.output[0].type.tensor_type.elem_type == TensorProto.BOOL
          assert converted_model.opset_import[0].version == to_opset
  
      # Test Greater Adapter: 9 -> 8
      def test_greater_9_8(self) -> None:
          from_opset = 9
          to_opset = 8
          data_type = TensorProto.UINT64
  
          nodes = [onnx.helper.make_node(
              "Greater",
              inputs=["X1", "X2"],
              outputs=["Y"]
          )]
  
          input_shape = [2, 3, 4]
          graph = helper.make_graph(
              nodes,
              "test_greater",
              [onnx.helper.make_tensor_value_info("X1", data_type, input_shape),
               onnx.helper.make_tensor_value_info("X2", data_type, input_shape)],
              [onnx.helper.make_tensor_value_info("Y", TensorProto.BOOL, input_shape)])
  
          converted_model = self._converted(graph, helper.make_operatorsetid("", from_opset), to_opset)
  
          assert converted_model.graph.node[2].op_type == "Greater"
          assert converted_model.graph.output[0].type.tensor_type.elem_type == TensorProto.BOOL
          assert converted_model.opset_import[0].version == to_opset
  
      # Test Less Adapter: 8 -> 9
      def test_less_8_9(self) -> None:
          from_opset = 8
          to_opset = 9
          data_type = TensorProto.FLOAT
  
          nodes = [onnx.helper.make_node(
              "Less",
              inputs=["X1", "X2"],
              outputs=["Y"]
          )]
  
          input_shape = [2, 3, 4]
          graph = helper.make_graph(
              nodes,
              "test_less",
              [onnx.helper.make_tensor_value_info("X1", data_type, input_shape),
               onnx.helper.make_tensor_value_info("X2", data_type, input_shape)],
              [onnx.helper.make_tensor_value_info("Y", TensorProto.BOOL, input_shape)])
  
          converted_model = self._converted(graph, helper.make_operatorsetid("", from_opset), to_opset)
  
          assert converted_model.graph.node[0].op_type == "Less"
          assert converted_model.graph.output[0].type.tensor_type.elem_type == TensorProto.BOOL
          assert converted_model.opset_import[0].version == to_opset
  
      # Test Less Adapter: 9 -> 8
      def test_less_9_8(self) -> None:
          from_opset = 9
          to_opset = 8
          data_type = TensorProto.UINT64
  
          nodes = [onnx.helper.make_node(
              "Less",
              inputs=["X1", "X2"],
              outputs=["Y"]
          )]
  
          input_shape = [2, 3, 4]
          graph = helper.make_graph(
              nodes,
              "test_less",
              [onnx.helper.make_tensor_value_info("X1", data_type, input_shape),
               onnx.helper.make_tensor_value_info("X2", data_type, input_shape)],
              [onnx.helper.make_tensor_value_info("Y", TensorProto.BOOL, input_shape)])
  
          converted_model = self._converted(graph, helper.make_operatorsetid("", from_opset), to_opset)
  
          assert converted_model.graph.node[2].op_type == "Less"
          assert converted_model.graph.output[0].type.tensor_type.elem_type == TensorProto.BOOL
          assert converted_model.opset_import[0].version == to_opset
  
      # Test MatMul Adapter: 8 -> 9
      def test_matmul_8_9(self) -> None:
          from_opset = 8
          to_opset = 9
          data_type = TensorProto.FLOAT
  
          nodes = [onnx.helper.make_node(
              "MatMul",
              inputs=["X1", "X2"],
              outputs=["Y"]
          )]
  
          graph = helper.make_graph(
              nodes,
              "test_matmul",
              [onnx.helper.make_tensor_value_info("X1", data_type, [3, 4]),
               onnx.helper.make_tensor_value_info("X2", data_type, [4, 3])],
              [onnx.helper.make_tensor_value_info("Y", data_type, [3, 3])])
  
          converted_model = self._converted(graph, helper.make_operatorsetid("", from_opset), to_opset)
  
          assert converted_model.graph.node[0].op_type == "MatMul"
          assert converted_model.graph.output[0].type.tensor_type.elem_type == data_type
          assert converted_model.opset_import[0].version == to_opset
  
      # Test MatMul Adapter: 9 -> 8
      def test_matmul_9_8(self) -> None:
          from_opset = 9
          to_opset = 8
          data_type = TensorProto.UINT64
  
          nodes = [onnx.helper.make_node(
              "MatMul",
              inputs=["X1", "X2"],
              outputs=["Y"]
          )]
  
          graph = helper.make_graph(
              nodes,
              "test_matmul",
              [onnx.helper.make_tensor_value_info("X1", data_type, [3, 4]),
               onnx.helper.make_tensor_value_info("X2", data_type, [4, 3])],
              [onnx.helper.make_tensor_value_info("Y", data_type, [3, 3])])
  
          converted_model = self._converted(graph, helper.make_operatorsetid("", from_opset), to_opset)
  
          assert converted_model.graph.node[2].op_type == "MatMul"
          assert converted_model.graph.output[0].type.tensor_type.elem_type == data_type
          assert converted_model.opset_import[0].version == to_opset
  
      # Test Gemm Adapter: 8 -> 9
      def test_gemm_8_9(self) -> None:
          from_opset = 8
          to_opset = 9
          data_type = TensorProto.FLOAT
  
          nodes = [onnx.helper.make_node(
              "Gemm",
              inputs=["X1", "X2", "X3"],
              outputs=["Y"]
          )]
  
          graph = helper.make_graph(
              nodes,
              "test_gemm",
              [onnx.helper.make_tensor_value_info("X1", data_type, [3, 4]),
               onnx.helper.make_tensor_value_info("X2", data_type, [4, 3]),
               onnx.helper.make_tensor_value_info("X3", data_type, [3, 3])],
              [onnx.helper.make_tensor_value_info("Y", data_type, [3, 3])])
  
          converted_model = self._converted(graph, helper.make_operatorsetid("", from_opset), to_opset)
  
          assert converted_model.graph.node[0].op_type == "Gemm"
          assert converted_model.graph.output[0].type.tensor_type.elem_type == data_type
          assert converted_model.opset_import[0].version == to_opset
  
      # Test Gemm Adapter: 9 -> 8
      def test_gemm_9_8(self) -> None:
          from_opset = 9
          to_opset = 8
          data_type = TensorProto.UINT64
  
          nodes = [onnx.helper.make_node(
              "Gemm",
              inputs=["X1", "X2", "X3"],
              outputs=["Y"]
          )]
  
          graph = helper.make_graph(
              nodes,
              "test_gemm",
              [onnx.helper.make_tensor_value_info("X1", data_type, [3, 4]),
               onnx.helper.make_tensor_value_info("X2", data_type, [4, 3]),
               onnx.helper.make_tensor_value_info("X3", data_type, [3, 3])],
              [onnx.helper.make_tensor_value_info("Y", data_type, [3, 3])])
  
          converted_model = self._converted(graph, helper.make_operatorsetid("", from_opset), to_opset)
  
          assert converted_model.graph.node[3].op_type == "Gemm"
          assert converted_model.graph.output[0].type.tensor_type.elem_type == data_type
          assert converted_model.opset_import[0].version == to_opset
  
      # Test Upsample Adapter: 8 -> 9
      def test_upsample_8_9(self) -> None:
          from_opset = 8
          to_opset = 9
          data_type = TensorProto.FLOAT
  
          nodes = [onnx.helper.make_node(
              "Upsample",
              inputs=["X"],
              outputs=["Y"],
              mode="nearest",
              scales=[1.0, 1.0, 2.0, 3.0],
          )]
  
          graph = helper.make_graph(
              nodes,
              "test_upsample_8_9",
              [onnx.helper.make_tensor_value_info("X", data_type, [1, 1, 2, 2])],
              [onnx.helper.make_tensor_value_info("Y", data_type, [1, 1, 4, 6])]
          )
  
          converted_model = self._converted(graph, helper.make_operatorsetid("", from_opset), to_opset)
  
          assert len(converted_model.graph.node) == 2
          assert converted_model.graph.node[0].op_type == "Constant"
          assert converted_model.graph.node[1].op_type == "Upsample"
          assert len(converted_model.graph.node[1].attribute) == 1
          assert converted_model.graph.node[1].attribute[0].name == "mode"
          assert converted_model.opset_import[0].version == to_opset
  
      # Test Helper for Upsample Adapter: 9 -> 8
      def helper_upsample_with_initializer(self, raw_scale: bool = False) -> None:
          from_opset = 9
          to_opset = 8
          data_type = TensorProto.FLOAT
  
          nodes = [onnx.helper.make_node(
              "Upsample",
              inputs=["X", "Scales"],
              outputs=["Y"],
              mode="nearest"
          )]
  
          scale_value = [1.0, 1.0, 2.0, 3.0]
          scale_tensor = onnx.helper.make_tensor("Scales", onnx.TensorProto.FLOAT, [4], bytes(struct.pack("4f", *scale_value)) if raw_scale else scale_value, raw_scale)
  
          graph = helper.make_graph(
              nodes,
              "test_upsample",
              [onnx.helper.make_tensor_value_info("X", data_type, [1, 1, 2, 2]),
               onnx.helper.make_tensor_value_info("Scales", data_type, [4])],
              [onnx.helper.make_tensor_value_info("Y", data_type, [1, 1, 4, 6])],
              [scale_tensor])
  
          converted_model = self._converted(graph, helper.make_operatorsetid("", from_opset), to_opset)
  
          assert converted_model.graph.node[0].op_type == "Upsample"
          assert len(converted_model.graph.initializer) == 0
          assert len(converted_model.graph.node[0].attribute) == 2
          assert converted_model.graph.node[0].attribute[1].name == "scales"
          assert converted_model.opset_import[0].version == to_opset
  
      # Test Helper for Upsample Adapter: 9 -> 8
      def helper_upsample_with_constant(self, raw_scale: bool = False) -> None:
          from_opset = 9
          to_opset = 8
          data_type = TensorProto.FLOAT
  
          scale_value = [1.0, 1.0, 2.0, 3.0]
          scale_tensor = onnx.helper.make_tensor("const_value", onnx.TensorProto.FLOAT, [4], bytes(struct.pack("4f", *scale_value)) if raw_scale else scale_value, raw_scale)
          nodes = [
              onnx.helper.make_node(
                  'Constant',
                  inputs=[],
                  outputs=['Constant_Output'],
                  value=scale_tensor),
              onnx.helper.make_node(
                  "Upsample",
                  inputs=["X", "Constant_Output"],
                  outputs=["Y"],
                  mode="nearest")]
  
          graph = helper.make_graph(
              nodes,
              "test_upsample",
              [onnx.helper.make_tensor_value_info("X", data_type, [1, 1, 2, 2])],
              [onnx.helper.make_tensor_value_info("Y", data_type, [1, 1, 4, 6])],
              value_info=[onnx.helper.make_tensor_value_info("Constant_Output", data_type, [4])])
  
          converted_model = self._converted(graph, helper.make_operatorsetid("", from_opset), to_opset)
  
          assert len(converted_model.graph.node) == 1
          assert converted_model.graph.node[0].op_type == "Upsample"
          assert len(converted_model.graph.node[0].attribute) == 2
          assert converted_model.graph.node[0].attribute[1].name == "scales"
          assert converted_model.opset_import[0].version == to_opset
  
      # Test Upsample Adapter: 9 -> 8
      def test_upsample_with_constant_node_9_8(self) -> None:
          self.helper_upsample_with_constant(raw_scale=False)
  
      # Test Upsample Adapter: 9 -> 8
      def test_upsample_with_initializer_9_8(self) -> None:
          self.helper_upsample_with_initializer(raw_scale=False)
  
      # Test Upsample Adapter: 9 -> 8
      def test_upsample_with_raw_initializer_9_8(self) -> None:
          self.helper_upsample_with_constant(raw_scale=True)
  
      # Test Upsample Adapter: 9 -> 8
      def test_upsample_with_raw_constant_node_9_8(self) -> None:
          self.helper_upsample_with_constant(raw_scale=True)
  
      # Test Scan Adapter: 8 -> 9
      def test_scan_8_9(self) -> None:
          from_opset = 8
          to_opset = 9
          data_type = TensorProto.FLOAT
  
          node1 = onnx.helper.make_node("Add", inputs=["sum_in", "next"], outputs=["sum_out"],)
          node2 = onnx.helper.make_node("Identity", inputs=["sum_out"], outputs=["scan_out"],)
          g = onnx.helper.make_graph(
              [node1, node2],
              "scan_body",
              [onnx.helper.make_tensor_value_info("sum_in", data_type, [2]),
               onnx.helper.make_tensor_value_info("next", data_type, [2])],
              [onnx.helper.make_tensor_value_info("sum_out", data_type, [2]),
               onnx.helper.make_tensor_value_info("scan_out", data_type, [2])]
          )
  
          no_sequence_lens = ''   # optional input, not supplied
          nodes = [onnx.helper.make_node(
              "Scan",
              inputs=[no_sequence_lens, "initial", "x"],
              outputs=["y", "z"],
              body=g,
              num_scan_inputs=1,
          )]
  
          initial = onnx.helper.make_tensor_value_info("initial", data_type, [1, 2])
          x = onnx.helper.make_tensor_value_info("x", data_type, [1, 3, 2])
          y = onnx.helper.make_tensor_value_info("y", data_type, [1, 2])
          z = onnx.helper.make_tensor_value_info("z", data_type, [1, 3, 2])
  
          graph = onnx.helper.make_graph(
              nodes, "test_scan_8_9", [initial, x], [y, z]
          )
  
          converted_model = self._converted(graph, helper.make_operatorsetid("", from_opset), to_opset)
  
          assert converted_model.graph.node[0].op_type == "Scan"
          assert converted_model.opset_import[0].version == to_opset
  
      # Test Cast Adapter: 8 -> 9
      def test_cast_8_9(self) -> None:
          from_opset = 8
          to_opset = 9
          data_type_from = TensorProto.FLOAT
          data_type_to = TensorProto.UINT32
  
          nodes = [onnx.helper.make_node(
              "Cast",
              inputs=["X"],
              outputs=["Y"],
              to=TensorProto.UINT32
          )]
  
          graph = helper.make_graph(
              nodes,
              "test_cast",
              [onnx.helper.make_tensor_value_info("X", data_type_from, [2, 3])],
              [onnx.helper.make_tensor_value_info("Y", data_type_to, [2, 3])])
  
          converted_model = self._converted(graph, helper.make_operatorsetid("", from_opset), to_opset)
  
          assert converted_model.graph.node[0].op_type == "Cast"
          assert converted_model.graph.output[0].type.tensor_type.elem_type == data_type_to
          assert converted_model.opset_import[0].version == to_opset
  
      #Test Split Adapter: 13 -> 12
      def test_split_13_12(self) -> None:
          nodes = [helper.make_node('Constant', [], ["split"],
                                    value=helper.make_tensor("", TensorProto.INT64, [2],
                                                             [2, 3])),
                   helper.make_node('Split', ["X", "split"], ["Y1", "Y2"])]
          graph = helper.make_graph(
              nodes,
              "test",
              [helper.make_tensor_value_info("X", TensorProto.FLOAT, (5,))],
              [helper.make_tensor_value_info("Y1", TensorProto.FLOAT, (2,)),
               helper.make_tensor_value_info("Y2", TensorProto.FLOAT, (3,))])
          converted_model = self._converted(graph, helper.make_operatorsetid(
              "", 13), 12)
          # Assert equality of graph and converted_model
          assert converted_model.graph.node[0].op_type == "Split"
          assert converted_model.opset_import[0].version == 12
  
      # Test Split Adapter: 12 -> 13
      def test_split_12_13(self) -> None:
          nodes = [helper.make_node('Split', ["X"], ["Y1", "Y2"], split=[2, 3])]
          graph = helper.make_graph(
              nodes,
              "test",
              [helper.make_tensor_value_info("X", TensorProto.FLOAT, (5,))],
              [helper.make_tensor_value_info("Y1", TensorProto.FLOAT, (2,)),
               helper.make_tensor_value_info("Y2", TensorProto.FLOAT, (3,))])
          converted_model = self._converted(graph, helper.make_operatorsetid(
              "", 12), 13)
          # Assert equality of graph and converted_model
          assert converted_model.graph.node[0].op_type == "Constant"
          assert converted_model.graph.node[1].op_type == "Split"
          assert converted_model.opset_import[0].version == 13
  
      # Test AxesInputToAttribute Adapter: 13 -> 12
      def test_axes_input_to_attr_13_12(self) -> None:
          nodes = [helper.make_node('Constant', [], ["axes"],
                                    value=helper.make_tensor("", TensorProto.INT64, [1],
                                                             [0])),
                   helper.make_node('ReduceSum', ["X", "axes"], ["Y"])]
          graph = helper.make_graph(
              nodes,
              "test",
              [helper.make_tensor_value_info("X", TensorProto.FLOAT, (5, 5))],
              [helper.make_tensor_value_info("Y", TensorProto.FLOAT, (1, 5))])
          converted_model = self._converted(graph, helper.make_operatorsetid(
              "", 13), 12)
          # Assert equality of graph and converted_model
          assert converted_model.graph.node[0].op_type == "ReduceSum"
          assert converted_model.opset_import[0].version == 12
  
      # Test AxesAttributeToInput Adapter: 12 -> 13
      def test_axes_attr_to_input_12_13(self) -> None:
          nodes = [helper.make_node('ReduceSum', ["X"], ["Y"], axes=[0])]
          graph = helper.make_graph(
              nodes,
              "test",
              [helper.make_tensor_value_info("X", TensorProto.FLOAT, (5, 5))],
              [helper.make_tensor_value_info("Y", TensorProto.FLOAT, (1, 5))])
          converted_model = self._converted(graph, helper.make_operatorsetid(
              "", 12), 13)
          # Assert equality of graph and converted_model
          assert converted_model.graph.node[0].op_type == "Constant"
          assert converted_model.opset_import[0].version == 13
  
      # Test Slice Adapter: 9 -> 10
      def test_slice_9_10(self) -> None:
          nodes = [helper.make_node('Slice', ["X"], ["Y"],
                                    axes=[0, 1],
                                    starts=[0, 0],
                                    ends=[3, 10])]
          graph = helper.make_graph(
              nodes,
              "test",
              [helper.make_tensor_value_info("X", TensorProto.FLOAT, (20, 10, 5))],
              [helper.make_tensor_value_info("Y", TensorProto.FLOAT, (3, 10, 5))])
          converted_model = self._converted(graph, helper.make_operatorsetid(
              "", 9), 10)
  
          assert converted_model.graph.node[0].op_type == "Constant"
          assert converted_model.graph.node[1].op_type == "Constant"
          assert converted_model.graph.node[2].op_type == "Constant"
          assert converted_model.graph.node[3].op_type == "Slice"
          assert converted_model.opset_import[0].version == 10
          assert len(converted_model.graph.node[3].input) == 4
          assert len(converted_model.graph.node[3].attribute) == 0
  
      # Test RNN Adapter: 13 -> 14
      def test_rnn_13_14(self) -> None:
          from_opset = 13
          to_opset = 14
          data_type = TensorProto.FLOAT
  
          seq_length = 1
          batch_size = 2
          input_size = 3
          num_directions = 1
          hidden_size = 5
  
          nodes = [onnx.helper.make_node(
              'RNN',
              inputs=['X', 'W', 'R'],
              outputs=['', 'Y_h'],
              hidden_size=hidden_size
          )]
  
          graph = helper.make_graph(
              nodes,
              "test_rnn",
              [onnx.helper.make_tensor_value_info("X", data_type, [seq_length, batch_size, input_size]),
               onnx.helper.make_tensor_value_info("W", data_type, [num_directions, hidden_size, input_size]),
               onnx.helper.make_tensor_value_info("R", data_type, [num_directions, hidden_size, hidden_size]),
               onnx.helper.make_tensor_value_info("B", data_type, [num_directions, 2 * hidden_size])],
              [onnx.helper.make_tensor_value_info("Y_h", data_type, [num_directions, batch_size, hidden_size])])
  
          converted_model = self._converted(graph, helper.make_operatorsetid("", from_opset), to_opset)
  
          assert converted_model.graph.node[0].op_type == "RNN"
          assert converted_model.opset_import[0].version == to_opset
          assert len(converted_model.graph.node[0].attribute) == 2
          assert converted_model.graph.node[0].attribute[1].name == "layout"
  
      # Test GRU Adapter: 13 -> 14
      def test_gru_13_14(self) -> None:
          from_opset = 13
          to_opset = 14
          data_type = TensorProto.FLOAT
  
          seq_length = 1
          batch_size = 2
          input_size = 3
          num_directions = 1
          hidden_size = 5
  
          nodes = [onnx.helper.make_node(
              'GRU',
              inputs=['X', 'W', 'R'],
              outputs=['', 'Y_h'],
              hidden_size=hidden_size
          )]
  
          graph = helper.make_graph(
              nodes,
              "test_gru",
              [onnx.helper.make_tensor_value_info("X", data_type, [seq_length, batch_size, input_size]),
               onnx.helper.make_tensor_value_info("W", data_type, [num_directions, 3 * hidden_size, input_size]),
               onnx.helper.make_tensor_value_info("R", data_type, [num_directions, 3 * hidden_size, hidden_size]),
               onnx.helper.make_tensor_value_info("B", data_type, [num_directions, 6 * hidden_size])],
              [onnx.helper.make_tensor_value_info("Y_h", data_type, [num_directions, batch_size, hidden_size])])
  
          converted_model = self._converted(graph, helper.make_operatorsetid("", from_opset), to_opset)
  
          assert converted_model.graph.node[0].op_type == "GRU"
          assert converted_model.opset_import[0].version == to_opset
          assert len(converted_model.graph.node[0].attribute) == 2
          assert converted_model.graph.node[0].attribute[1].name == "layout"
  
      # Test LSTM Adapter: 13 -> 14
      def test_lstm_13_14(self) -> None:
          from_opset = 13
          to_opset = 14
          data_type = TensorProto.FLOAT
  
          seq_length = 1
          batch_size = 2
          input_size = 3
          num_directions = 1
          hidden_size = 5
  
          nodes = [onnx.helper.make_node(
              'LSTM',
              inputs=['X', 'W', 'R'],
              outputs=['', 'Y_h'],
              hidden_size=hidden_size
          )]
  
          graph = helper.make_graph(
              nodes,
              "test_lstm",
              [onnx.helper.make_tensor_value_info("X", data_type, [seq_length, batch_size, input_size]),
               onnx.helper.make_tensor_value_info("W", data_type, [num_directions, 4 * hidden_size, input_size]),
               onnx.helper.make_tensor_value_info("R", data_type, [num_directions, 4 * hidden_size, hidden_size]),
               onnx.helper.make_tensor_value_info("B", data_type, [num_directions, 8 * hidden_size])],
              [onnx.helper.make_tensor_value_info("Y_h", data_type, [num_directions, batch_size, hidden_size])])
  
          converted_model = self._converted(graph, helper.make_operatorsetid("", from_opset), to_opset)
  
          assert converted_model.graph.node[0].op_type == "LSTM"
          assert converted_model.opset_import[0].version == to_opset
          assert len(converted_model.graph.node[0].attribute) == 2
          assert converted_model.graph.node[0].attribute[1].name == "layout"
  
      # Test RNN Adapter: 14 -> 13
      def test_rnn_14_13(self) -> None:
          from_opset = 14
          to_opset = 13
          data_type = TensorProto.FLOAT
  
          seq_length = 1
          batch_size = 2
          input_size = 3
          num_directions = 1
          hidden_size = 5
  
          nodes = [onnx.helper.make_node(
              'RNN',
              inputs=['X', 'W', 'R'],
              outputs=['', 'Y_h'],
              hidden_size=hidden_size,
              layout=0,
          )]
  
          graph = helper.make_graph(
              nodes,
              "test_rnn",
              [onnx.helper.make_tensor_value_info("X", data_type, [seq_length, batch_size, input_size]),
               onnx.helper.make_tensor_value_info("W", data_type, [num_directions, hidden_size, input_size]),
               onnx.helper.make_tensor_value_info("R", data_type, [num_directions, hidden_size, hidden_size]),
               onnx.helper.make_tensor_value_info("B", data_type, [num_directions, 2 * hidden_size])],
              [onnx.helper.make_tensor_value_info("Y_h", data_type, [num_directions, batch_size, hidden_size])])
  
          converted_model = self._converted(graph, helper.make_operatorsetid("", from_opset), to_opset)
  
          assert converted_model.graph.node[0].op_type == "RNN"
          assert converted_model.opset_import[0].version == to_opset
          assert len(converted_model.graph.node[0].attribute) == 1
  
      # Test GRU Adapter: 14 -> 13
      def test_gru_14_13(self) -> None:
          from_opset = 14
          to_opset = 13
          data_type = TensorProto.FLOAT
  
          seq_length = 1
          batch_size = 2
          input_size = 3
          num_directions = 1
          hidden_size = 5
  
          nodes = [onnx.helper.make_node(
              'GRU',
              inputs=['X', 'W', 'R'],
              outputs=['', 'Y_h'],
              hidden_size=hidden_size,
              layout=0,
          )]
  
          graph = helper.make_graph(
              nodes,
              "test_gru",
              [onnx.helper.make_tensor_value_info("X", data_type, [seq_length, batch_size, input_size]),
               onnx.helper.make_tensor_value_info("W", data_type, [num_directions, 3 * hidden_size, input_size]),
               onnx.helper.make_tensor_value_info("R", data_type, [num_directions, 3 * hidden_size, hidden_size]),
               onnx.helper.make_tensor_value_info("B", data_type, [num_directions, 6 * hidden_size])],
              [onnx.helper.make_tensor_value_info("Y_h", data_type, [num_directions, batch_size, hidden_size])])
  
          converted_model = self._converted(graph, helper.make_operatorsetid("", from_opset), to_opset)
  
          assert converted_model.graph.node[0].op_type == "GRU"
          assert converted_model.opset_import[0].version == to_opset
          assert len(converted_model.graph.node[0].attribute) == 1
  
      # Test LSTM Adapter: 14 -> 13
      def test_lstm_14_13(self) -> None:
          from_opset = 14
          to_opset = 13
          data_type = TensorProto.FLOAT
  
          seq_length = 1
          batch_size = 2
          input_size = 3
          num_directions = 1
          hidden_size = 5
  
          nodes = [onnx.helper.make_node(
              'LSTM',
              inputs=['X', 'W', 'R'],
              outputs=['', 'Y_h'],
              hidden_size=hidden_size,
              layout=0,
          )]
  
          graph = helper.make_graph(
              nodes,
              "test_lstm",
              [onnx.helper.make_tensor_value_info("X", data_type, [seq_length, batch_size, input_size]),
               onnx.helper.make_tensor_value_info("W", data_type, [num_directions, 4 * hidden_size, input_size]),
               onnx.helper.make_tensor_value_info("R", data_type, [num_directions, 4 * hidden_size, hidden_size]),
               onnx.helper.make_tensor_value_info("B", data_type, [num_directions, 8 * hidden_size])],
              [onnx.helper.make_tensor_value_info("Y_h", data_type, [num_directions, batch_size, hidden_size])])
  
          converted_model = self._converted(graph, helper.make_operatorsetid("", from_opset), to_opset)
  
          assert converted_model.graph.node[0].op_type == "LSTM"
          assert converted_model.opset_import[0].version == to_opset
          assert len(converted_model.graph.node[0].attribute) == 1
  
      # Test that subgraphs are converted
      def test_if_subgraph_10_11(self) -> None:
          from_opset = 10
          to_opset = 11
          data_type = TensorProto.FLOAT
          data_shape = [2]
  
          subg1_node = [onnx.helper.make_node(
              'Clip',
              inputs=['sub_in'],
              outputs=['sub_out'],
              min=2.0,
              max=3.0
          )]
          subg1_input = [
              onnx.helper.make_tensor_value_info('sub_in', data_type, data_shape)
          ]
          subg1_output = [
              onnx.helper.make_tensor_value_info('sub_out', data_type, data_shape)
          ]
          subg1 = helper.make_graph(subg1_node, "then_g", subg1_input, subg1_output)
  
          subg2_node = [onnx.helper.make_node(
              'Clip',
              inputs=['sub_in'],
              outputs=['sub_out'],
              min=2.0,
              max=3.0
          )]
          subg2_input = [
              onnx.helper.make_tensor_value_info('sub_in', data_type, data_shape)
          ]
          subg2_output = [
              onnx.helper.make_tensor_value_info('sub_out', data_type, data_shape)
          ]
          subg2 = helper.make_graph(subg2_node, "then_g", subg2_input, subg2_output)
  
          node = [onnx.helper.make_node(
              'If',
              inputs=['cond'],
              outputs=['out'],
              then_branch=subg1,
              else_branch=subg2
          )]
          input = [
              onnx.helper.make_tensor_value_info('cond', TensorProto.BOOL, [])
          ]
          output = [
              onnx.helper.make_tensor_value_info('out', data_type, data_shape)
          ]
          init = [helper.make_tensor('sub_in', data_type, data_shape, [4.0, 5.0])]
          graph = helper.make_graph(node, 'test_subgraphs', input, output, init)
  
          converted = self._converted(graph, helper.make_operatorsetid('', from_opset), to_opset)
  
          assert converted.graph.node[0].op_type == 'If'
          assert converted.opset_import[0].version == to_opset
          assert converted.graph.node[0].attribute[0].g.node[2].op_type == 'Clip'
          assert len(converted.graph.node[0].attribute[0].g.node[2].attribute) == 0
          assert converted.graph.node[0].attribute[1].g.node[2].op_type == 'Clip'
          assert len(converted.graph.node[0].attribute[1].g.node[2].attribute) == 0
  
      # Use initializer as node inputs (instead of graph input)
      # to test whether IR (version_converter) can handle it
      def test_initializer_not_in_input_above_ir4(self):  # type: () -> None
          nodes = [helper.make_node('BatchNormalization', ["X", "scale", "B",
              "mean", "var"], ["Y"])]
  
          scale_value = [0.55, 0.72]
          scale_tensor = onnx.helper.make_tensor("scale", onnx.TensorProto.FLOAT, [2], scale_value)
          b_value = [0.60, 0.54]
          b_tensor = onnx.helper.make_tensor("B", onnx.TensorProto.FLOAT, [2], b_value)
          mean_value = [0.42, 0.65]
          mean_tensor = onnx.helper.make_tensor("mean", onnx.TensorProto.FLOAT, [2], mean_value)
          var_value = [0.44, 0.89]
          var_tensor = onnx.helper.make_tensor("var", onnx.TensorProto.FLOAT, [2], var_value)
  
          graph = helper.make_graph(
              nodes,
              "test",
              [helper.make_tensor_value_info("X", TensorProto.FLOAT, (1, 2, 2, 3))],
              [helper.make_tensor_value_info("Y", TensorProto.FLOAT, (1, 2, 2, 3))],
              [scale_tensor, b_tensor, mean_tensor, var_tensor])
  
          converted_model = self._converted(graph, helper.make_operatorsetid(
              "", 11), 12)
          # Assert equality of graph and converted_model
          assert converted_model.graph.node[0].op_type == "BatchNormalization"
          assert converted_model.opset_import[0].version == 12
  
  
  if __name__ == '__main__':
      unittest.main()
  