Проверить, чтобы две функции работали одновременно? - PullRequest
2 голосов
/ 25 мая 2019

Предположим, у меня есть функция runConcurrently(f1: Int => Int, f2: Int => Int): (Int, Int), которая возвращает результаты f1 и f2.

Теперь я хотел бы написать тест, чтобы убедиться, что f1 и f2 запустить одновременно при вызове runConcurrently.Я хотел бы сделать тест детерминированным и максимально эффективным.

Как бы вы предложили написать тест?

PS Я не хочу связывать его с какой-либо конкретной тестовой средой илибиблиотека.Единственной зависимостью должен быть Scala / Java SDK.

Ответы [ 3 ]

5 голосов
/ 26 мая 2019

Самое близкое, что вы можете сделать, это использовать какое-то общее условие, которое используют обе функции:

def runConcurrently(f1: => Int, f2: => Int): Future[(Int, Int)] = 
   Future(f1) zip Future(f2)

 val sem1 = new Semaphore(0)
 val sem2 = new Semaphore(0)

 def f1 = {
    sem1.release
    sem2.acquire
    1
 }

 def f2 = {
    sem2.release
    sem1.acquire
    2
}

Await.result(runConcurrently(f1, f2), 1 second) shouldBe (1,2)

Идея состоит в том, что ни одна из функций не может завершиться до того, как другая хотя бы запустится.Таким образом, попытка запустить их последовательно никогда не закончится, и вы получите тайм-аут.

В частности, этот код не будет работать, если вы попытаетесь запустить его с однопоточным контекстом выполнения.

0 голосов
/ 25 мая 2019

Уродливое решение для уродливой проблемы:

object Test extends App {
  def runConcurrently(f1: () => Int, f2: () => Int): (Int, Int) = {
    import ExecutionContext.Implicits.global
    val f = Future(f1())
    val g = Future(f2())
    Await.result(f.zip(g), Duration.Inf)
  }

  @volatile var start1: Long = 0
  @volatile var start2: Long = 0
  @volatile var end1: Long = 0
  @volatile var end2: Long = 0

  val f1 : () => Int = {
    case x : Unit => {
      start1 = System.nanoTime()
      Thread.sleep(1000)
      end1 = System.nanoTime()
      1
    }
  }

  val f2 : () => Int = {
    case x : Unit => {
      start2 = System.nanoTime()
      Thread.sleep(1000)
      end2 = System.nanoTime()
      1
    }
  }

  runConcurrently(f1, f2)

  assert(start1 < end2)
  assert(start2 < end1)

}
0 голосов
/ 25 мая 2019

Как уже говорилось ранее, это, вероятно, не всегда работает, а также далеко не детерминировано.
Но это может служить вам.

final class FunctionMeter[-I, +O](private[this] val underlying: I => O) {
  private[this] var start: Long = _
  private[this] var finish: Long = _

  def getStartTime: Long = start
  def getFinishTime: Long = finish

  def getFun: I => O = input => {
    start = System.nanoTime()
    val output = underlying(input)
    finish = System.nanoTime()
    output
  }
}

def test(f1: Int => Int, f2: Int => Int): Boolean {
  val m1 = new FunctionMeter(f1)
  val m2 = new FunctionMeter(f2)

  runConcurrently(m1.getFunction, m2.getFunction)

  m2.getStartTime < m1.getFinishTime && m1.getStartTime < m2.getFinishTime
}

В любом случае, я с Димой, что это не то, что вы должны проверить.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...