All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.gatling.commons.stats.assertion.AssertionValidator.scala Maven / Gradle / Ivy

There is a newer version: 3.13.1
Show newest version
/**
 * Copyright 2011-2016 GatlingCorp (http://gatling.io)
 *
 * Licensed 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 io.gatling.commons.stats.assertion

import io.gatling.commons.stats._
import io.gatling.commons.validation.{ Failure, Success, Validation }

object AssertionValidator {

  type ValidatedRequestPath = Validation[Option[Status] => List[GeneralStats]]
  type StatsByStatus = Option[Status] => List[GeneralStats]

  def validateAssertions(dataReader: GeneralStatsSource): List[AssertionResult] =
    dataReader.assertions.map(validateAssertion(_, dataReader))

  private def validateAssertion(assertion: Assertion, source: GeneralStatsSource): AssertionResult = {

    val printablePath = assertion.path.printable

    assertion.path match {
      case Global =>
        resolveTarget(assertion, status => List(source.requestGeneralStats(None, None, status)), printablePath)

      case ForAll =>
        val paths = source.statsPaths.collect { case path: RequestStatsPath => path }
        val statsList: StatsByStatus = status => paths.map {
          case RequestStatsPath(request, group) =>
            source.requestGeneralStats(Some(request), group, status)
        }
        resolveTarget(assertion, statsList, printablePath)

      case Details(parts) if parts.isEmpty =>
        resolveTarget(assertion, status => List(source.requestGeneralStats(None, None, status)), printablePath)

      case Details(parts) =>
        val generalStats: ValidatedRequestPath = findPath(parts, source) match {
          case None =>
            Failure(s"Could not find stats matching assertion path $parts")

          case Some(RequestStatsPath(request, group)) =>
            Success(status => List(source.requestGeneralStats(Some(request), group, status)))

          case Some(GroupStatsPath(group)) =>
            Success(status => List(source.groupCumulatedResponseTimeGeneralStats(group, status)))
        }
        generalStats match {
          case Success(stats) => resolveTarget(assertion, stats, printablePath)
          case Failure(msg)   => AssertionResult(assertion, result = false, msg, Nil)
        }
    }
  }

  private def findPath(parts: List[String], source: GeneralStatsSource): Option[StatsPath] =
    source.statsPaths.find { statsPath =>
      val path = statsPath match {
        case RequestStatsPath(request, group) =>
          group.map(_.hierarchy :+ request).getOrElse(List(request))

        case GroupStatsPath(group) =>
          group.hierarchy
      }
      path == parts
    }

  private def resolveTarget(assertion: Assertion, stats: StatsByStatus, path: String) = {

    val printableTarget = assertion.target.printable

    val realValues = assertion.target match {
      case MeanRequestsPerSecondTarget => stats(None).map(s => math.round(s.meanRequestsPerSec).toInt)
      case target: CountTarget         => resolveCountTargetRealValues(target, stats)
      case target: TimeTarget          => resolveTimeTargetRealValues(target, stats)
    }

    resolveCondition(assertion, path, printableTarget, realValues)
  }

  private def resolveCountTargetRealValues(target: CountTarget, stats: StatsByStatus): List[Int] = {

    val resolvedStats = target.metric match {
      case AllRequests        => stats(None)
      case FailedRequests     => stats(Some(KO))
      case SuccessfulRequests => stats(Some(OK))
    }

    target.selection match {
      case Count => resolvedStats.map(_.count)
      case Percent =>
        val metricCountsAndAllCounts = resolvedStats.map(_.count).zip(stats(None).map(_.count))
        metricCountsAndAllCounts.map { case (metricCount, allCount) => math.round(metricCount.toDouble / allCount * 100).toInt }
      case PerMillion =>
        val metricCountsAndAllCounts = resolvedStats.map(_.count).zip(stats(None).map(_.count))
        metricCountsAndAllCounts.map { case (metricCount, allCount) => math.round(metricCount.toDouble / allCount * 1000000).toInt }
    }
  }

  private def resolveTimeTargetRealValues(target: TimeTarget, stats: StatsByStatus): List[Int] = {

    val resolvedStats = target.metric match {
      case ResponseTime => stats(None)
    }

    target.selection match {
      case Min                => resolvedStats.map(_.min)
      case Max                => resolvedStats.map(_.max)
      case Mean               => resolvedStats.map(_.mean)
      case StandardDeviation  => resolvedStats.map(_.stdDev)
      case Percentiles(value) => resolvedStats.map(_.percentile(value))
    }
  }

  private def resolveCondition(assertion: Assertion, path: String, printableTarget: String, realValues: List[Int]) = {

    val printableCondition = assertion.condition.printable

      def assertionResult(result: Boolean, expectedValueMessage: Any) =
        AssertionResult(assertion, result, s"$path: $printableTarget $printableCondition $expectedValueMessage", realValues)

    assertion.condition match {
      case LessThan(upper)       => assertionResult(realValues.forall(_ <= upper), upper)
      case GreaterThan(lower)    => assertionResult(realValues.forall(_ >= lower), lower)
      case Is(exactValue)        => assertionResult(realValues.forall(_ == exactValue), exactValue)
      case Between(lower, upper) => assertionResult(realValues.forall(v => lower <= v && v <= upper), s"$lower and $upper")
      case In(elements)          => assertionResult(realValues.forall(elements contains), elements)
    }
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy