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

io.gatling.http.action.ws.fsm.WsActor.scala Maven / Gradle / Ivy

There is a newer version: 3.13.1
Show newest version
/*
 * Copyright 2011-2019 GatlingCorp (https://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.http.action.ws.fsm

import scala.concurrent.duration.FiniteDuration

import io.gatling.commons.stats.{ KO, OK, Status }
import io.gatling.commons.util.Clock
import io.gatling.core.action.Action
import io.gatling.core.config.GatlingConfiguration
import io.gatling.core.session.Session
import io.gatling.core.stats.StatsEngine
import io.gatling.http.check.ws.{ WsBinaryFrameCheck, WsFrameCheck, WsFrameCheckSequence, WsTextFrameCheck }
import io.gatling.http.client.{ Request, WebSocket }
import io.gatling.http.engine.HttpEngine
import io.gatling.http.protocol.HttpProtocol

import akka.actor.Props
import io.netty.handler.codec.http.cookie.Cookie

final case class PerformInitialConnect(session: Session, initialConnectNext: Action)
final case class WebSocketConnected(webSocket: WebSocket, cookies: List[Cookie], timestamp: Long)
sealed trait SendFrame {
  def actionName: String
  def session: Session
  def next: Action
  def copyWithSession(newSession: Session): SendFrame
}
final case class SendTextFrame(actionName: String, message: String, checkSequences: List[WsFrameCheckSequence[WsTextFrameCheck]], session: Session, next: Action) extends SendFrame {
  override def copyWithSession(newSession: Session): SendFrame = copy(session = newSession)
}
final case class SendBinaryFrame(actionName: String, message: Array[Byte], checkSequences: List[WsFrameCheckSequence[WsBinaryFrameCheck]], session: Session, next: Action) extends SendFrame {
  override def copyWithSession(newSession: Session): SendFrame = copy(session = newSession)
}

sealed trait FrameReceived

final case class TextFrameReceived(message: String, timestamp: Long) extends FrameReceived
final case class BinaryFrameReceived(message: Array[Byte], timestamp: Long) extends FrameReceived
final case class WebSocketClosed(code: Int, reason: String, timestamp: Long)
final case class WebSocketCrashed(t: Throwable, timestamp: Long)
final case class ClientCloseRequest(actionName: String, session: Session, next: Action)
final case class Timeout(id: Long)

object WsActor {

  val TimeoutTimerName = "timeout"

  def props(
    wsName:               String,
    connectRequest:       Request,
    subprotocol:          Option[String],
    connectActionName:    String,
    connectCheckSequence: List[WsFrameCheckSequence[WsFrameCheck]],
    onConnected:          Option[Action],
    statsEngine:          StatsEngine,
    httpEngine:           HttpEngine,
    httpProtocol:         HttpProtocol,
    clock:                Clock,
    configuration:        GatlingConfiguration
  ) =
    Props(new WsActor(
      wsName,
      connectRequest,
      subprotocol,
      connectActionName,
      connectCheckSequence,
      onConnected,
      statsEngine,
      httpEngine,
      httpProtocol,
      clock,
      configuration
    ))
}

class WsActor(
    val wsName:               String,
    val connectRequest:       Request,
    val subprotocol:          Option[String],
    val connectActionName:    String,
    val connectCheckSequence: List[WsFrameCheckSequence[WsFrameCheck]],
    val onConnected:          Option[Action],
    val statsEngine:          StatsEngine,
    val httpEngine:           HttpEngine,
    val httpProtocol:         HttpProtocol,
    val clock:                Clock,
    val configuration:        GatlingConfiguration
) extends WsActorFSM
  with WhenInit
  with WhenConnecting
  with WhenPerformingCheck
  with WhenIdle
  with WhenClosing
  with WhenCrashed {

  private var _timeoutId = 0L
  protected def scheduleTimeout(dur: FiniteDuration): Long = {
    val curr = _timeoutId
    setTimer(WsActor.TimeoutTimerName, Timeout(curr), dur, repeat = false)
    _timeoutId += 1
    curr
  }

  protected def cancelTimeout(): Unit =
    cancelTimer(WsActor.TimeoutTimerName)

  //[fl]
  //
  //
  //[fl]

  protected def logResponse(session: Session, actionName: String, start: Long, end: Long, status: Status, code: Option[String], reason: Option[String]): Session = {
    val newSession = session.logGroupRequestTimings(start, end)
    val newSessionWithMark = if (status == KO) newSession.markAsFailed else newSession
    statsEngine.logResponse(newSessionWithMark, actionName, start, end, status, code, reason)
    newSessionWithMark
  }

  protected def logUnmatchedServerMessage(session: Session): Unit =
    statsEngine.logResponse(session, wsName, clock.nowMillis, Long.MinValue, OK, None, None)

  startWith(Init, InitData)

  whenUnhandled {
    case Event(message, state) =>
      logger.debug(s"Can't handle $message in state $state")
      stay()
  }

  initialize()
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy