/*
 * Copyright 2014-2019 JetBrains s.r.o and contributors. Use of this source code is governed by the Apache 2.0 license.
 */

package io.ktor.client.tests.cio

import io.ktor.util.cio.*
import kotlinx.coroutines.*
import org.junit.Test
import java.util.concurrent.atomic.*
import kotlin.test.*

internal const val TEST_SIZE = 100
internal const val FAIL_TIMEOUT = 100L

@Suppress("KDocMissingDocumentation")
class SemaphoreTest {

    @Test
    fun passTest() = runBlocking {
        val semaphore = Semaphore(1)

        semaphore.enter()
        val task = launch {
            semaphore.enter()
        }

        assertFailsWith<TimeoutCancellationException> {
            runBlocking {
                withTimeout(100) {
                    task.join()
                }
            }
        }

        semaphore.leave()
        task.join()
    }

    @Test
    fun emptyTest() = runBlocking {
        val semaphore = Semaphore(1)

        semaphore.enter()

        val jobs = List(TEST_SIZE) {
            GlobalScope.launch {
                semaphore.enter()
                semaphore.leave()
            }
        }

        semaphore.leave()

        jobs.forEach {
            it.join()
        }
    }

    @Test
    fun borderTest() = runBlocking {
        val semaphore = Semaphore(10)
        repeat(10) {
            semaphore.enter()
        }

        val job = GlobalScope.launch {
            semaphore.enter()
        }

        repeat(TEST_SIZE) {
            assertFails {
                runBlocking {
                    withTimeout(FAIL_TIMEOUT) {
                        job.join()
                    }
                }
            }
        }

    }
}
