/*
 * 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.
 */
package system.redundancy

import com.jayway.restassured.RestAssured
import com.jayway.restassured.config.SSLConfig
import common._
import org.junit.runner.RunWith
import org.scalatest.junit.JUnitRunner
import org.scalatest.{BeforeAndAfterAll, FlatSpec, Matchers}
import spray.json.DefaultJsonProtocol.StringJsonFormat
import spray.json.{pimpAny, _}
import system.CloudantUtil

/**
 * These tests verify that a cloudant redundancy (master/slave) configuration
 * works as expected.  They will only run properly in an environment with two
 * cloudant containers running concurrently and env var HOST_INDEX set to host0 in
 * one container and host1 in the other.  This test also assumes that redis and
 * the active endpoint authorization are configured.  For the auth set the
 * ENDPOINT_AUTH env var in your containers to match the testing.auth property
 * found in your whisk.properties.  To configure redis simply set the REDIS_URL
 * env var in your containers to point to the openwhisk redis container and make
 * sure the container is deployed.  You can run redis.yml to deploy it.
 */
@RunWith(classOf[JUnitRunner])
class CloudantRedundancyTests
    extends FlatSpec
    with Matchers
    with BeforeAndAfterAll
    with WskTestHelpers {

    val wskprops = WskProps()
    val wsk = new Wsk
    val myCloudantCreds = CloudantUtil.Credential.makeFromVCAPFile("cloudantNoSQLDB", this.getClass.getSimpleName)
    val edgeHost = WhiskProperties.getEdgeHost
    val auth = WhiskProperties.getBasicAuth
    val user = auth.fst
    val password = auth.snd

    val endpointPrefix = s"https://$user:$password@$edgeHost/cloudanttrigger/worker0/"
    val defaultAction = Some(TestUtils.getTestActionFilename("hello.js"))

    behavior of "Cloudant redundancy tests"

    it should "fire cloudant trigger before the swap" in withAssetCleaner(wskprops) {
        (wp, assetHelper) =>
            implicit val wskprops = wp // shadow global props and make implicit
            val triggerName = s"dummyCloudantTrigger-${System.currentTimeMillis}"
            val ruleName = s"dummyAlarmsRule-${System.currentTimeMillis}"
            val actionName = s"dummyAlarmsAction-${System.currentTimeMillis}"
            val packageName = "dummyCloudantPackage"
            val feed = "changes"

            try {
                CloudantUtil.setUp(myCloudantCreds)

                // the package cloudant should be there
                val packageGetResult = wsk.pkg.get("/whisk.system/cloudant")
                println("fetched package cloudant")
                packageGetResult.stdout should include("ok")

                // create package binding
                assetHelper.withCleaner(wsk.pkg, packageName) {
                    (pkg, name) => pkg.bind("/whisk.system/cloudant", name)
                }

                // create action
                assetHelper.withCleaner(wsk.action, actionName) { (action, name) =>
                    action.create(name, defaultAction)
                }

                // create whisk stuff
                val feedCreationResult = assetHelper.withCleaner(wsk.trigger, triggerName, confirmDelete = false) {
                    (trigger, name) =>
                        trigger.create(name, feed = Some(s"$packageName/$feed"), parameters = Map(
                            "username" -> myCloudantCreds.user.toJson,
                            "password" -> myCloudantCreds.password.toJson,
                            "host" -> myCloudantCreds.host().toJson,
                            "dbname" -> myCloudantCreds.dbname.toJson))
                }

                // create rule
                assetHelper.withCleaner(wsk.rule, ruleName) { (rule, name) =>
                    rule.create(name, trigger = triggerName, action = actionName)
                }

                Thread.sleep(3000)

                // create a test doc in the sample db
                println("create a test doc and wait for trigger")
                CloudantUtil.createDocument(myCloudantCreds, "{\"test\":\"test_doc1\"}")

                // get activation list of the trigger, expecting exactly 1
                val activations = wsk.activation.pollFor(N = 1, Some(triggerName), retries = 30).length
                println(s"Found activation size (should be exactly 1): $activations")
                withClue("Change feed trigger count: ") { activations should be(1) }

                // delete the whisk trigger, which must also delete the feed
                wsk.trigger.delete(triggerName)
            } finally {
                CloudantUtil.unsetUp(myCloudantCreds)
            }
    }

    it should "perform active swap by setting host0 active=false" in {
        val endpointURL = endpointPrefix + "0/active?active=false"
        val expectedResult = "{\"worker\":\"worker0\",\"host\":\"host0\",\"active\":\"swapping\"}".parseJson.asJsObject

        makeGetCallWithExpectedResult(endpointURL, expectedResult)
    }

    it should "verify active swap by checking for host0 active=false" in {
        val endpointURL = endpointPrefix + "0/active"
        val expectedResult = "{\"worker\":\"worker0\",\"host\":\"host0\",\"active\":false}".parseJson.asJsObject

        Thread.sleep(3000)
        makeGetCallWithExpectedResult(endpointURL, expectedResult)
    }

    it should "verify active swap by checking for host1 active=true" in {
        val endpointURL = endpointPrefix + "1/active"
        val expectedResult = "{\"worker\":\"worker0\",\"host\":\"host1\",\"active\":true}".parseJson.asJsObject

        makeGetCallWithExpectedResult(endpointURL, expectedResult)
    }

    it should "fire cloudant trigger again after the swap" in withAssetCleaner(wskprops) {
        (wp, assetHelper) =>
            implicit val wskprops = wp // shadow global props and make implicit
            val triggerName = s"dummyCloudantTrigger-${System.currentTimeMillis}"
            val ruleName = s"dummyAlarmsRule-${System.currentTimeMillis}"
            val actionName = s"dummyAlarmsAction-${System.currentTimeMillis}"
            val packageName = "dummyCloudantPackage"
            val feed = "changes"

            try {
                CloudantUtil.setUp(myCloudantCreds)

                // the package cloudant should be there
                val packageGetResult = wsk.pkg.get("/whisk.system/cloudant")
                println("fetched package cloudant")
                packageGetResult.stdout should include("ok")

                // create package binding
                assetHelper.withCleaner(wsk.pkg, packageName) {
                    (pkg, name) => pkg.bind("/whisk.system/cloudant", name)
                }

                // create action
                assetHelper.withCleaner(wsk.action, actionName) { (action, name) =>
                    action.create(name, defaultAction)
                }

                // create whisk stuff
                val feedCreationResult = assetHelper.withCleaner(wsk.trigger, triggerName, confirmDelete = false) {
                    (trigger, name) =>
                        trigger.create(name, feed = Some(s"$packageName/$feed"), parameters = Map(
                            "username" -> myCloudantCreds.user.toJson,
                            "password" -> myCloudantCreds.password.toJson,
                            "host" -> myCloudantCreds.host().toJson,
                            "dbname" -> myCloudantCreds.dbname.toJson))
                }

                // create rule
                assetHelper.withCleaner(wsk.rule, ruleName) { (rule, name) =>
                    rule.create(name, trigger = triggerName, action = actionName)
                }

                Thread.sleep(3000)

                // create a test doc in the sample db
                println("create a test doc and wait for trigger")
                CloudantUtil.createDocument(myCloudantCreds, "{\"test\":\"test_doc1\"}")

                // get activation list of the trigger, expecting exactly 1
                val activations = wsk.activation.pollFor(N = 1, Some(triggerName), retries = 30).length
                println(s"Found activation size (should be exactly 1): $activations")
                withClue("Change feed trigger count: ") { activations should be(1) }

                // delete the whisk trigger, which must also delete the feed
                wsk.trigger.delete(triggerName)
            } finally {
                CloudantUtil.unsetUp(myCloudantCreds)
            }
    }

    private def makeGetCallWithExpectedResult(endpointURL: String, expectedResult: JsObject) = {
        val response = RestAssured.
                given().
                config(RestAssured.config().sslConfig(new SSLConfig().relaxedHTTPSValidation())).
                get(endpointURL)
        assert(response.statusCode() == 200)
        var result = response.body.asString.parseJson.asJsObject
        JsObject(result.fields - "hostMachine") shouldBe expectedResult
    }

    override def afterAll() {
        //swap back to original configuration
        RestAssured.
                given().
                config(RestAssured.config().sslConfig(new SSLConfig().relaxedHTTPSValidation())).
                get(endpointPrefix + "0/active?active=true")
    }

}
