summaryrefslogtreecommitdiff
path: root/clientserver/test/src/mill/clientserver/ClientServerTests.scala
blob: a02e2733ff6dfeecd555c74e29aa1ea9f7b47ba6 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
package mill.clientserver
import java.io._
import java.nio.file.Path

import utest._
class EchoServer extends ServerMain[Int]{
  def main0(args: Array[String],
            stateCache: Option[Int],
            mainInteractive: Boolean,
            stdin: InputStream,
            stdout: PrintStream,
            stderr: PrintStream) = {

    val reader = new BufferedReader(new InputStreamReader(stdin))
    val str = reader.readLine()
    stdout.println(str + args(0))
    stdout.flush()
    stderr.println(str.toUpperCase + args(0))
    stderr.flush()
    (true, None)
  }
}

object ClientServerTests extends TestSuite{
  def initStreams() = {
    val in = new ByteArrayInputStream("hello\n".getBytes())
    val out = new ByteArrayOutputStream()
    val err = new ByteArrayOutputStream()
    (in, out, err)
  }
  def init() = {
    val tmpDir = java.nio.file.Files.createTempDirectory("")
    val locks = new MemoryLocks()

    (tmpDir, locks)
  }

  def tests = Tests{
    'hello - {
      val (tmpDir, locks) = init()

      def spawnEchoServer(): Unit = {
        new Thread(() => new Server(
          tmpDir.toString,
          new EchoServer(),
          () => (),
          1000,
          locks
        ).run()).start()
      }


      def runClient(arg: String) = {
        val (in, out, err) = initStreams()
        locks.clientLock.lockBlock{
          val c = new Client(
            tmpDir.toString,
            () => spawnEchoServer(),
            locks,
            in,
            out,
            err
          )
          c.run(Array(arg))
          (new String(out.toByteArray), new String(err.toByteArray))
        }
      }

      // Make sure the simple "have the client start a server and
      // exchange one message" workflow works from end to end.

      assert(
        locks.clientLock.probe(),
        locks.serverLock.probe(),
        locks.processLock.probe()
      )

      val (out1, err1) = runClient("world")

      assert(
        out1 == "helloworld\n",
        err1 == "HELLOworld\n"
      )

      // Give a bit of time for the server to release the lock and
      // re-acquire it to signal to the client that it's done
      Thread.sleep(100)

      assert(
        locks.clientLock.probe(),
        !locks.serverLock.probe(),
        !locks.processLock.probe()
      )

      // A seecond client in sequence connect to the same server
      val (out2, err2) = runClient(" WORLD")

      assert(
        out2 == "hello WORLD\n",
        err2 == "HELLO WORLD\n"
      )

      // Make sure the server times out of not used for a while
      Thread.sleep(2000)
      assert(
        locks.clientLock.probe(),
        locks.serverLock.probe(),
        locks.processLock.probe()
      )

      // Have a third client spawn/connect-to a new server at the same path
      val (out3, err3) = runClient(" World")
      assert(
        out3 == "hello World\n",
        err3 == "HELLO World\n"
      )
    }
  }
}