test_process.inko 4.73 KB
Newer Older
1 2 3
import std::process::(self, Receiver, Sender)
import std::test
import std::test::assert
4
import std::time::Instant
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

test.group('std::process::Sender.send') do (g) {
  g.test('Sending a message to a process') {
    let pid = process.spawn {
      let parent = process.receive as Integer

      process.send(pid: parent, message: parent)
    }

    Sender.new(pid).send(process.current)

    assert.equal(process.receive as Integer, process.current)
  }
}

test.group('std::process::Sender.pid') do (g) {
  g.test('Obtaining a PID of the receiving end of a Sender') {
    let sender = Sender.new(process.current)

    assert.equal(sender.pid, process.current)
  }
}

test.group('std::process::Receiver.receive') do (g) {
  g.test('Receiving a message without a timeout') {
    let receiver: Receiver!(Integer) = Receiver.new

    process.send(pid: process.current, message: 10)

    assert.equal(receiver.receive, 10)
  }

  g.test('Receiving a message with a timeout') {
    let receiver: Receiver!(Integer) = Receiver.new
    let message = receiver.receive(0.0001)

    assert.equal(message, Nil)
  }
}

test.group('std::process.current') do (g) {
  g.test('Obtaining the PID of the current process') {
    assert.true(process.current >= 0)
  }
}

test.group('std::process.send') do (g) {
  g.test('Sending a message to a process') {
    let message = process.send(pid: process.current, message: 'testing')
    let received = process.receive as String

    assert.equal(message, 'testing')
    assert.equal(received, message)
  }
}

test.group('std::process.receive') do (g) {
  g.test('Receiving a message without a timeout') {
    process.send(pid: process.current, message: 'testing')

    let received = process.receive as String

    assert.equal(received, 'testing')
  }

  g.test('Receiving a message with a timeout') {
    let received = process.receive(0.001) as ?String

    assert.equal(received, Nil)
  }
}

test.group('std::process.spawn') do (g) {
  g.test('Spawning a process') {
    let pid = process.spawn {}

    assert.true(pid >= 0)
  }
}

test.group('std::process.channel') do (g) {
  g.test('Sending and receiving messages using a Sender and Receiver') {
    let sender = process.channel!(Integer) lambda (receiver) {
      let pid = *receiver.receive

      process.send(pid: pid, message: pid)
    }

    sender.send(process.current)

    assert.equal(process.receive as Integer, process.current)
  }
}

test.group('std::process.blocking') do (g) {
  g.test('Performing a blocking operation') {
    assert.equal(process.blocking({ 10 }), 10)
  }
}

test.group('std::process.suspend') do (g) {
  g.test('Suspending a process') {
    assert.equal(process.suspend, Nil)
  }

  g.test('Suspending a process for a minimum amount of time') {
111
    let start = Instant.new
112 113 114 115
    let wait = 0.01

    process.suspend(wait)

116
    let duration = start.elapsed.to_float
117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197

    assert.true(duration >= wait)
  }
}

test.group('std::process.terminate') do (g) {
  g.test('Terminating the current process') {
    let pid = process.spawn {
      let parent = process.receive as Integer

      process.terminate

      # This code will never run, unless `process.terminate` somehow doesn't
      # terminate the current process.
      process.send(pid: parent, message: parent)
    }

    process.send(pid: pid, message: process.current)

    # Only if `process.terminate` _does not_ terminate the process will we
    # receive a message.
    let message = process.receive(0.01) as ?Integer

    assert.equal(message, Nil)
  }
}

test.group('std::process.panicking') do (g) {
  g.test('Registering a custom panic handler') {
    let pid = process.spawn {
      let parent = process.receive as Integer

      process.panicking do (error) {
        process.send(pid: parent, message: error)
      }

      process.panic('example panic')
    }

    process.send(pid: pid, message: process.current)

    let error = process.receive as String

    assert.equal(error, 'example panic')
  }
}

test.group('std::process.defer') do (g) {
  g.test('Deferring the execution of a Block') {
    let mut number = 0

    do {
      process.defer {
        # This will be executed _after_ `number = 1` below.
        number = 2
      }

      number = 1
    }.call

    assert.equal(number, 2)
  }
}

test.group('std::process.pinned') do (g) {
  g.test('Pinning a process to an OS thread') {
    # There is no reliable way of testing whether we are truly pinned, without
    # using some sort of FFI example that uses thread-local storage. Since that
    # is far too much to test here, we'll just test that the block returns the
    # proper value.
    assert.equal(process.pinned({ 10 }), 10)
  }
}

test.group('std::process.panic') do (g) {
  g.test('Causing a process to panic') {
    assert.panic {
      process.panic('This is a panic')
    }
  }
}