mdeuser commented on a change in pull request #2944: Replace test cases of api gateway with REST URL: https://github.com/apache/incubator-openwhisk/pull/2944#discussion_r150541717
########## File path: tests/src/test/scala/whisk/core/cli/test/BaseApiGwTests.scala ########## @@ -0,0 +1,165 @@ +/* + * 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 whisk.core.cli.test + +import java.io.File +import java.time.Instant + +import scala.collection.mutable.ArrayBuffer +import scala.concurrent.duration._ + +import org.junit.runner.RunWith + +import org.scalatest.BeforeAndAfterAll +import org.scalatest.BeforeAndAfterEach +import org.scalatest.junit.JUnitRunner + +import common.TestHelpers +import common.TestUtils._ +import common.WhiskProperties +import common.BaseWsk +import common.WskProps +import common.WskTestHelpers + +/** + * Tests for testing the CLI "api" subcommand. Most of these tests require a deployed backend. + */ +@RunWith(classOf[JUnitRunner]) +abstract class BaseApiGwTests extends TestHelpers with WskTestHelpers with BeforeAndAfterEach with BeforeAndAfterAll { + + implicit val wskprops = WskProps() + val wsk: BaseWsk + + // This test suite makes enough CLI invocations in 60 seconds to trigger the OpenWhisk + // throttling restriction. To avoid CLI failures due to being throttled, track the + // CLI invocation calls and when at the throttle limit, pause the next CLI invocation + // with exactly enough time to relax the throttling. + val maxActionsPerMin = WhiskProperties.getMaxActionInvokesPerMinute() + val invocationTimes = new ArrayBuffer[Instant]() + + // Custom CLI properties file + val cliWskPropsFile = File.createTempFile("wskprops", ".tmp") + + /** + * Expected to be called before each test. + * Assumes that each test will not invoke more than 5 actions and + * settle the throttle when there isn't enough capacity to handle the test. + */ + def checkThrottle(maxInvocationsBeforeThrottle: Int = maxActionsPerMin, expectedActivationsPerTest: Int = 5) = { + val t = Instant.now + val tminus60 = t.minusSeconds(60) + val invocationsLast60Seconds = invocationTimes.filter(_.isAfter(tminus60)).sorted + val invocationCount = invocationsLast60Seconds.length + println(s"Action invokes within last minute: ${invocationCount}") + + if (invocationCount >= maxInvocationsBeforeThrottle) { + // Instead of waiting a fixed 60 seconds to settle the throttle, + // calculate a wait time that will clear out about half of the + // current invocations (assuming even distribution) from the + // next 60 second period. + val oldestInvocationInLast60Seconds = invocationsLast60Seconds.head + + // Take the oldest invocation time in this 60 second period. To clear + // this invocation from the next 60 second period, the wait time will be + // (60sec - oldest invocation's delta time away from the period end). + // This will clear all of the invocations from the next period at the + // expense of potentially waiting uncessarily long. Instead, this calculation + // halves the delta time as a compromise. + val throttleTime = 60.seconds.toMillis - ((t.toEpochMilli - oldestInvocationInLast60Seconds.toEpochMilli) / 2) + println(s"Waiting ${throttleTime} milliseconds to settle the throttle") + Thread.sleep(throttleTime) + } + + invocationTimes += Instant.now + } + + override def beforeEach() = { + //checkThrottle() + } + + /* + * Create a CLI properties file for use by the tests + */ + override def beforeAll() = { + cliWskPropsFile.deleteOnExit() + val wskprops = WskProps(token = "SOME TOKEN") + wskprops.writeFile(cliWskPropsFile) + println(s"wsk temporary props file created here: ${cliWskPropsFile.getCanonicalPath()}") + } + + /* + * Forcibly clear the throttle so that downstream tests are not affected by + * this test suite + */ + override def afterAll() = { + // Check and settle the throttle so that this test won't cause issues with and follow on tests + checkThrottle(30) + } + + def apiCreate(basepath: Option[String] = None, + relpath: Option[String] = None, + operation: Option[String] = None, + action: Option[String] = None, + apiname: Option[String] = None, + swagger: Option[String] = None, + responsetype: Option[String] = None, + expectedExitCode: Int = SUCCESS_EXIT, + cliCfgFile: Option[String] = Some(cliWskPropsFile.getCanonicalPath()))( + implicit wskpropsOverride: WskProps): RunResult = { + + println("parmssss is fdasdadasdddddddddsfsd") + checkThrottle() + println("create is fdasdadasdddddddddsfsd") Review comment: @houshengbo - are these two `println` statements still needed? ---------------------------------------------------------------- This is an automated message from the Apache Git Service. To respond to the message, please log on GitHub and use the URL above to go to the specific comment. For queries about this service, please contact Infrastructure at: [email protected] With regards, Apache Git Services
