diff --git a/TensorFlow.Kernel.UnitTest/TensorFlow.Kernel.UnitTest.csproj b/TensorFlow.Kernel.UnitTest/TensorFlow.Kernel.UnitTest.csproj
new file mode 100644
index 00000000..a52a4cda
--- /dev/null
+++ b/TensorFlow.Kernel.UnitTest/TensorFlow.Kernel.UnitTest.csproj
@@ -0,0 +1,24 @@
+
+
+
+ net6.0
+ enable
+ enable
+
+ false
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/TensorFlow.Kernel.UnitTest/array_ops/concat_op_test.cs b/TensorFlow.Kernel.UnitTest/array_ops/concat_op_test.cs
new file mode 100644
index 00000000..cfa8f0fb
--- /dev/null
+++ b/TensorFlow.Kernel.UnitTest/array_ops/concat_op_test.cs
@@ -0,0 +1,65 @@
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using Tensorflow;
+using Tensorflow.NumPy;
+using TensorFlow;
+using static Tensorflow.Binding;
+using static Tensorflow.KerasApi;
+
+namespace TensorFlow.Kernel.UnitTest
+{
+ [TestClass]
+ public class concat_op_test
+ {
+ [TestMethod]
+ public void testConcatEmpty()
+ {
+ var t1 = tf.constant(new int[] { });
+ var t2 = tf.constant(new int[] { });
+ var c = array_ops.concat(new[] { t1, t2 }, 0);
+ var expected = np.array(new int[] { });
+ Assert.IsTrue(Enumerable.SequenceEqual(expected.ToArray(), c.numpy().ToArray()));
+ }
+
+ [TestMethod]
+ public void testConcatNegativeAxis()
+ {
+ var t1 = tf.constant(new int[,] {{ 1, 2, 3 }, { 4, 5, 6 } });
+ var t2 = tf.constant(new int[,] { { 7, 8, 9 }, { 10, 11, 12 } });
+ var c = array_ops.concat(new[] { t1, t2 }, -2);
+ var expected = np.array(new int[,,] { { { 1, 2, 3 }, { 4, 5, 6 } }, { { 7, 8, 9 }, { 10, 11, 12 } } });
+ Assert.IsTrue(Enumerable.SequenceEqual(expected.ToArray(), c.numpy().ToArray()));
+
+ c = array_ops.concat(new[] { t1, t2 }, -1);
+ expected = np.array(new int[,] { { 1, 2, 3, 7, 8, 9 }, { 4, 5, 6, 10, 11, 12 } });
+ Assert.IsTrue(Enumerable.SequenceEqual(expected.ToArray(), c.numpy().ToArray()));
+ }
+
+ [TestMethod]
+ [DataRow(TF_DataType.TF_INT32)]
+ [DataRow(TF_DataType.TF_INT64)]
+ [DataRow(TF_DataType.TF_UINT32)]
+ [DataRow(TF_DataType.TF_UINT64)]
+ public void testConcatDtype(TF_DataType dtype)
+ {
+ var t1 = tf.constant(new int[,] { { 1, 2, 3 }, { 4, 5, 6 } }, dtype: dtype);
+ var t2 = tf.constant(new int[,] { { 7, 8, 9 }, { 10, 11, 12 } }, dtype: dtype);
+ var c = array_ops.concat(new[] { t1, t2 }, 1);
+ var expected = np.array(new int[,] { { 1, 2, 3, 7, 8, 9 }, { 4, 5, 6, 10, 11, 12 } });
+ Assert.IsTrue(Enumerable.SequenceEqual(expected.ToArray(), tf.cast(c, TF_DataType.TF_INT32).numpy().ToArray()));
+
+ }
+
+ [TestMethod]
+ [DataRow(TF_DataType.TF_INT32)]
+ [DataRow(TF_DataType.TF_INT64)]
+ public void testConcatAxisType(TF_DataType dtype)
+ {
+ var t1 = tf.constant(new int[,] { { 1, 2, 3 }, {4, 5, 6 } });
+ var t2 = tf.constant(new int[,] { { 7, 8, 9 }, { 10, 11, 12 } });
+ var c = array_ops.concat(new[] { t1, t2 }, tf.constant(1, dtype: dtype));
+ var expected = np.array(new int[,] { { 1, 2, 3, 7, 8, 9 }, { 4, 5, 6, 10, 11, 12 } });
+ Assert.IsTrue(Enumerable.SequenceEqual(expected.ToArray(), tf.cast(c, TF_DataType.TF_INT32).numpy().ToArray()));
+ }
+
+ }
+}
diff --git a/TensorFlow.NET.sln b/TensorFlow.NET.sln
index 87729e27..a246407b 100644
--- a/TensorFlow.NET.sln
+++ b/TensorFlow.NET.sln
@@ -39,6 +39,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Tensorflow.Benchmark", "too
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Tensorflow.Console", "tools\TensorFlowNET.Console\Tensorflow.Console.csproj", "{1DC32255-BA1F-4D6D-A9C9-5BD5ED71CAA0}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TensorFlow.Kernel.UnitTest", "TensorFlow.Kernel.UnitTest\TensorFlow.Kernel.UnitTest.csproj", "{C08C6692-4818-46C1-8462-2F0CC40C9152}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -322,6 +324,24 @@ Global
{1DC32255-BA1F-4D6D-A9C9-5BD5ED71CAA0}.Release|x64.Build.0 = Release|x64
{1DC32255-BA1F-4D6D-A9C9-5BD5ED71CAA0}.Release|x86.ActiveCfg = Release|Any CPU
{1DC32255-BA1F-4D6D-A9C9-5BD5ED71CAA0}.Release|x86.Build.0 = Release|Any CPU
+ {C08C6692-4818-46C1-8462-2F0CC40C9152}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {C08C6692-4818-46C1-8462-2F0CC40C9152}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {C08C6692-4818-46C1-8462-2F0CC40C9152}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {C08C6692-4818-46C1-8462-2F0CC40C9152}.Debug|x64.Build.0 = Debug|Any CPU
+ {C08C6692-4818-46C1-8462-2F0CC40C9152}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {C08C6692-4818-46C1-8462-2F0CC40C9152}.Debug|x86.Build.0 = Debug|Any CPU
+ {C08C6692-4818-46C1-8462-2F0CC40C9152}.GPU|Any CPU.ActiveCfg = Debug|Any CPU
+ {C08C6692-4818-46C1-8462-2F0CC40C9152}.GPU|Any CPU.Build.0 = Debug|Any CPU
+ {C08C6692-4818-46C1-8462-2F0CC40C9152}.GPU|x64.ActiveCfg = Debug|Any CPU
+ {C08C6692-4818-46C1-8462-2F0CC40C9152}.GPU|x64.Build.0 = Debug|Any CPU
+ {C08C6692-4818-46C1-8462-2F0CC40C9152}.GPU|x86.ActiveCfg = Debug|Any CPU
+ {C08C6692-4818-46C1-8462-2F0CC40C9152}.GPU|x86.Build.0 = Debug|Any CPU
+ {C08C6692-4818-46C1-8462-2F0CC40C9152}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {C08C6692-4818-46C1-8462-2F0CC40C9152}.Release|Any CPU.Build.0 = Release|Any CPU
+ {C08C6692-4818-46C1-8462-2F0CC40C9152}.Release|x64.ActiveCfg = Release|Any CPU
+ {C08C6692-4818-46C1-8462-2F0CC40C9152}.Release|x64.Build.0 = Release|Any CPU
+ {C08C6692-4818-46C1-8462-2F0CC40C9152}.Release|x86.ActiveCfg = Release|Any CPU
+ {C08C6692-4818-46C1-8462-2F0CC40C9152}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -342,6 +362,7 @@ Global
{D24FCAA5-548C-4251-B226-A1B6535D0845} = {E1A5D2B7-10AF-4876-85C0-7714EF274214}
{C23563DB-FE21-48E7-A411-87A109E4A899} = {E1A5D2B7-10AF-4876-85C0-7714EF274214}
{1DC32255-BA1F-4D6D-A9C9-5BD5ED71CAA0} = {E1A5D2B7-10AF-4876-85C0-7714EF274214}
+ {C08C6692-4818-46C1-8462-2F0CC40C9152} = {1B0918B9-65AD-4F34-A287-AF4597B27DBD}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {2DEAD3CC-486B-4918-A607-50B0DE7B114A}