﻿/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace Apache.Ignite.Core.Tests.Deployment
{
    extern alias TestDll2;
    using System;
    using System.Configuration;
    using System.IO;
    using System.Threading;
    using Apache.Ignite.Core.Cluster;
    using Apache.Ignite.Core.Compute;
    using Apache.Ignite.Core.Deployment;
    using Apache.Ignite.Core.Impl;
    using Apache.Ignite.Core.Impl.Common;
    using Apache.Ignite.Core.Impl.Deployment;
    using Apache.Ignite.Core.Tests.Process;
    using Apache.Ignite.NLog;
    using NUnit.Framework;
    using Address = TestDll2::Apache.Ignite.Core.Tests.TestDll2.Address;

    /// <summary>
    /// Tests peer assembly loading feature:
    /// when user-defined type is not found within loaded assemblies on remote node,
    /// corresponding assembly is sent and loaded automatically.
    /// </summary>
    public class PeerAssemblyLoadingTest
    {
        /// <summary>
        /// Tests that peer loading does not happen when not enabled in config, and error message is informative.
        /// </summary>
        [Test]
        public void TestDisabledPeerLoading()
        {
            TestDeployment(remoteCompute =>
            {
                var ex = Assert.Throws<AggregateException>(() => remoteCompute.Call(new ProcessNameFunc()))
                    .InnerException;

                Assert.IsNotNull(ex);
                Assert.AreEqual("Compute job has failed on remote node, examine InnerException for details.", 
                    ex.Message);

                Assert.IsNotNull(ex.InnerException);
                Assert.AreEqual("Failed to deserialize the job [errType=BinaryObjectException, errMsg=No matching " +
                                "type found for object", ex.InnerException.Message.Substring(0, 102));
            }, false);
        }

        /// <summary>
        /// Tests single assembly deployment (basic test).
        /// </summary>
        [Test]
        public void TestSingleAssembly()
        {
            TestDeployment(remoteCompute =>
            {
                Assert.AreEqual("Apache.Ignite", remoteCompute.Call(new ProcessNameFunc()));
            });
        }

        /// <summary>
        /// Tests that a type which requires multiple assemblies can be peer deployed.
        /// </summary>
        [Test]
        public void TestMultipleAssemblies()
        {
            TestDeployment(remoteCompute =>
            {
                // GetAddressFunc requires Tests and Examples assemblies.
                var result = remoteCompute.Apply(new GetAddressFunc(), 3);

                Assert.IsNotNull(result);

                Assert.AreEqual(3, result.Zip);
                Assert.AreEqual("addr3", result.Street);
            });
        }

        /// <summary>
        /// Tests that a type which requires multiple assemblies can be peer deployed.
        /// </summary>
        [Test]
        public void TestMultipleAssembliesIndirectDependency()
        {
            TestDeployment(remoteCompute =>
            {
                // Arg is object, but value is from Examples assembly.
                Assert.AreEqual("Apache.IgniteAddress [street=Central, zip=2]", remoteCompute.Call(
                    new ProcessNameFunc {Arg = new Address("Central", 2)}));
            });
        }

        /// <summary>
        /// Tests that a type which requires multiple assemblies can be peer deployed.
        /// </summary>
        [Test]
        public void TestMultipleAssembliesIndirectDependencyMultiLevel()
        {
            TestDeployment(remoteCompute =>
            {
                // Arg is object, value is from Apache.Ignite.Log4Net, and it further depends on NLog.
                Assert.AreEqual("Apache.IgniteApache.Ignite.NLog.IgniteNLogLogger", remoteCompute.Call(
                    new ProcessNameFunc {Arg = new IgniteNLogLogger()}));
            });
        }

        /// <summary>
        /// Tests the runtime dependency: AssemblyResolve event fires during job execution,
        /// not during deserialization. This happens with static classes, for example.
        /// </summary>
        [Test]
        public void TestRuntimeDependency()
        {
            TestDeployment(remoteCompute =>
            {
                Assert.AreEqual("dcba", remoteCompute.Apply(new RuntimeDependencyFunc(), "abcd"));
            });
        }

        /// <summary>
        /// Tests the cache get operation on remote node.
        /// </summary>
        [Test]
        public void TestCacheGetOnRemoteNode()
        {
            TestDeployment(remoteCompute =>
            {
                var cache = remoteCompute.ClusterGroup.Ignite.GetOrCreateCache<int, Address>("addr");
                cache[1] = new Address("street", 123);

                // This will fail for <object, object> func, because cache operations are not p2p-enabled.
                // However, generic nature of the func causes Address to be peer-deployed before cache.Get call.
                var func = new CacheGetFunc<int, Address>
                {
                    CacheName = cache.Name,
                    Key = 1
                };

                var res = remoteCompute.Call(func);
                Assert.AreEqual("street", res.Street);
            });
        }

        /// <summary>
        /// Tests the peer deployment.
        /// </summary>
        public static void TestDeployment(Action<ICompute> test, bool enablePeerDeployment = true)
        {
            TestDeployment((IClusterGroup remoteCluster) => test(remoteCluster.GetCompute()), enablePeerDeployment);
        }

        /// <summary>
        /// Tests the peer deployment.
        /// </summary>
        private static void TestDeployment(Action<IClusterGroup> test, bool enablePeerDeployment = true)
        {
            TestDeployment(ignite => test(ignite.GetCluster().ForRemotes()), enablePeerDeployment);
        }

        /// <summary>
        /// Tests the peer deployment.
        /// </summary>
        public static void TestDeployment(Action<IIgnite> test, bool enablePeerDeployment = true)
        {
            // Copy Apache.Ignite.exe and Apache.Ignite.Core.dll 
            // to a separate folder so that it does not locate our assembly automatically.
            var folder = PathUtils.GetTempDirectoryName();
            foreach (var asm in new[] {typeof(IgniteRunner).Assembly, typeof(Ignition).Assembly, typeof(ConfigurationManager).Assembly})
            {
                Assert.IsNotNull(asm.Location);
                File.Copy(asm.Location, Path.Combine(folder, Path.GetFileName(asm.Location)));
            }

            // ReSharper disable once AssignNullToNotNullAttribute
            var cfgMan = Path.Combine(
                Path.GetDirectoryName(typeof(Ignition).Assembly.Location),
                "System.Configuration.ConfigurationManager.dll");

            File.Copy(cfgMan, Path.Combine(folder, Path.GetFileName(cfgMan)));

            var exePath = Path.Combine(folder, "Apache.Ignite.exe");

            // Start separate Ignite process without loading current dll.
            // ReSharper disable once AssignNullToNotNullAttribute
            var config = Path.Combine(
                Path.GetDirectoryName(typeof(PeerAssemblyLoadingTest).Assembly.Location),
                "Deployment",
                "peer_assembly_app.config");

            var proc = IgniteProcess.Start(exePath, IgniteHome.Resolve(), null,
                "-ConfigFileName=" + config, "-ConfigSectionName=igniteConfiguration");

            try
            {
                Thread.Sleep(300);
                Assert.IsFalse(proc.HasExited);

                // Start Ignite and execute computation on remote node.
                var cfg = new IgniteConfiguration(TestUtils.GetTestConfiguration())
                {
                    PeerAssemblyLoadingMode = enablePeerDeployment
                        ? PeerAssemblyLoadingMode.CurrentAppDomain
                        : PeerAssemblyLoadingMode.Disabled
                };

                using (var ignite = Ignition.Start(cfg))
                {
                    Assert.IsTrue(ignite.WaitTopology(2));

                    for (var i = 0; i < 10; i++)
                    {
                        test(ignite);
                    }
                }
            }
            finally
            {
                proc.Kill();
                proc.WaitForExit();
            }
        }

        /// <summary>
        /// Tests that we are not entering endless loop while resolving an assembly from one node to another
        /// https://issues.apache.org/jira/browse/IGNITE-11690
        /// </summary>
        [Test]
        public void TestMissingAssemblyResolutionWithEnabledPeerLoadingFlag()
        {
            // We need to simulate two nodes that will be interacted with each other.
            Ignition.Start(GetConfig());
            var ignite = Ignition.Start(GetConfig());

            // Create separate thread in order to avoid program block due to the endless loop.
            var workerThread = new Thread(() =>
            {
                PeerAssemblyResolver.LoadAssemblyAndGetType("Unavailable.Assembly, unavailable, Ver=1",
                    (IIgniteInternal) ignite, Guid.Empty);
            });
            workerThread.Start();

            bool isAssemblyResolved = workerThread.Join(TimeSpan.FromSeconds(10));
            if (!isAssemblyResolved)
            {
                // Ignite instances should be disposed in TearDown method.
                workerThread.Abort();
            }

            Assert.IsTrue(isAssemblyResolved, "Execution cancelled by timeout.");
        }

        private static IgniteConfiguration GetConfig()
        {
            var cfg = TestUtils.GetTestConfiguration(null, Guid.NewGuid().ToString());
            cfg.PeerAssemblyLoadingMode = PeerAssemblyLoadingMode.CurrentAppDomain;
            return cfg;
        }

        /// <summary>
        /// Tears down the test.
        /// </summary>
        [TearDown]
        public void TearDown()
        {
            Ignition.StopAll(true);
            IgniteProcess.KillAll();
        }
    }
}
