|
1 | 1 | /* global describe, before, after, it */
|
2 | 2 |
|
3 | 3 | const assert = require('assert')
|
| 4 | +const child_process = require('child_process') // eslint-disable-line camelcase |
| 5 | +const fs = require('fs') |
4 | 6 | const mockery = require('mockery')
|
5 | 7 |
|
6 | 8 | describe('tor unit tests', () => {
|
@@ -77,4 +79,140 @@ describe('tor unit tests', () => {
|
77 | 79 | assert.deepStrictEqual(['foo', Buffer.from('barbaz'), 12],
|
78 | 80 | tor.torControlParseKV('xfoo=barbaz quux=zoty', 1, 20))
|
79 | 81 | })
|
| 82 | + |
| 83 | + const spawnTor = (torDaemon) => { |
| 84 | + const argv = [ |
| 85 | + '-f', '-', |
| 86 | + '--defaults-torrc', '/nonexistent', |
| 87 | + '--ignore-missing-torrc', |
| 88 | + // Set the directory authority to something that doesn't exist |
| 89 | + // so tor won't actually talk to the network (much?). |
| 90 | + '--dirauthority', '0.0.0.0:443 0000000000000000000000000000000000000000', |
| 91 | + '--socksport', 'auto', |
| 92 | + '--controlport', 'auto', |
| 93 | + '--controlportwritetofile', tor.torControlPortPath(), |
| 94 | + '--cookieauthentication', '1', |
| 95 | + '--cookieauthfile', tor.torControlCookiePath(), |
| 96 | + '--datadirectory', tor.torDataDirPath(), |
| 97 | + '--log', 'notice stderr' |
| 98 | + ] |
| 99 | + const spawnOpts = { |
| 100 | + env: {}, |
| 101 | + argv0: 'brave-test-tor' // make the process easily greppable |
| 102 | + } |
| 103 | + const torPath = 'app/extensions/bin/tor' |
| 104 | + const proc = child_process.spawn(torPath, argv, spawnOpts) |
| 105 | + const bufsplit = (buf, delim) => { |
| 106 | + const chunks = [] |
| 107 | + let i = 0 |
| 108 | + let j |
| 109 | + while ((j = buf.indexOf(delim, i)) !== -1) { |
| 110 | + chunks.push(buf.slice(i, j)) |
| 111 | + i = j + 1 |
| 112 | + } |
| 113 | + if (i !== 0) { // Trailing chunk. |
| 114 | + chunks.push(buf.slice(i)) |
| 115 | + } |
| 116 | + return chunks |
| 117 | + } |
| 118 | + const termify = (prefix, buf) => { |
| 119 | + // TODO(riastradh): make content safe for terminal |
| 120 | + const chunks = bufsplit(buf, 0x0a) // LF |
| 121 | + for (let i = 0; i < chunks.length; i++) { |
| 122 | + if (i + 1 === chunks.length && chunks[i].length === 0) { |
| 123 | + continue |
| 124 | + } |
| 125 | + console.log(prefix + chunks[i]) |
| 126 | + } |
| 127 | + } |
| 128 | + proc.stderr.on('data', (chunk) => termify('tor: stderr: ', chunk)) |
| 129 | + proc.stdout.on('data', (chunk) => termify('tor: stdout: ', chunk)) |
| 130 | + proc.on('error', (err) => { |
| 131 | + console.log(`error: ${err}`) |
| 132 | + torDaemon.kill() |
| 133 | + }) |
| 134 | + proc.on('exit', () => { |
| 135 | + console.log(`exited`) |
| 136 | + torDaemon.kill() |
| 137 | + }) |
| 138 | + proc.stdin.end('') |
| 139 | + return proc |
| 140 | + } |
| 141 | + |
| 142 | + const bravePath = () => fakeElectron.app.getPath('userData') |
| 143 | + before((cb) => { |
| 144 | + fs.mkdir(bravePath(), 0o700, (err) => { |
| 145 | + if (err && err.code !== 'EEXIST') { |
| 146 | + assert.ifError(err) |
| 147 | + } |
| 148 | + cb() |
| 149 | + }) |
| 150 | + }) |
| 151 | + after((cb) => { |
| 152 | + fs.rmdir(bravePath(), (err) => { |
| 153 | + assert.ifError(!err) |
| 154 | + cb() |
| 155 | + }) |
| 156 | + }) |
| 157 | + |
| 158 | + it('tor daemon start then watch', (callback) => { |
| 159 | + // TODO(riastradh): broken test |
| 160 | + return callback() |
| 161 | + /* eslint-disable no-unreachable */ |
| 162 | + const torDaemon = new tor.TorDaemon() |
| 163 | + torDaemon.setup(() => { |
| 164 | + const proc = spawnTor(torDaemon) |
| 165 | + setTimeout(() => { |
| 166 | + torDaemon.start() |
| 167 | + const timeoutLaunch = setTimeout(() => { |
| 168 | + assert.fail('tor daemon failed to start after 1sec') |
| 169 | + }, 2000) |
| 170 | + torDaemon.on('launch', (socksAddr) => { |
| 171 | + clearTimeout(timeoutLaunch) |
| 172 | + proc.kill('SIGTERM') |
| 173 | + const timeoutKill = setTimeout(() => { |
| 174 | + proc.kill('SIGKILL') |
| 175 | + assert.fail('tor daemon failed to exit after 1sec') |
| 176 | + }, 2000) |
| 177 | + proc.on('exit', () => { |
| 178 | + clearTimeout(timeoutKill) |
| 179 | + torDaemon.kill() |
| 180 | + callback() |
| 181 | + }) |
| 182 | + }) |
| 183 | + }, 500) |
| 184 | + }) |
| 185 | + /* eslint-enable no-unreachable */ |
| 186 | + }) |
| 187 | + |
| 188 | + it('tor daemon watch then start', (callback) => { |
| 189 | + // TODO(riastradh): broken test |
| 190 | + return callback() |
| 191 | + /* eslint-disable no-unreachable */ |
| 192 | + const torDaemon = new tor.TorDaemon() |
| 193 | + torDaemon.setup(() => { |
| 194 | + torDaemon.start() |
| 195 | + setTimeout(() => { |
| 196 | + const proc = spawnTor(torDaemon) |
| 197 | + const timeoutLaunch = setTimeout(() => { |
| 198 | + console.log(`launch timeout`) |
| 199 | + assert.fail('tor daemon failed to start after 1sec') |
| 200 | + }, 2000) |
| 201 | + torDaemon.on('launch', (socksAddr) => { |
| 202 | + clearTimeout(timeoutLaunch) |
| 203 | + proc.kill('SIGTERM') |
| 204 | + const timeoutKill = setTimeout(() => { |
| 205 | + proc.kill('SIGKILL') |
| 206 | + assert.fail('tor daemon failed to exit after 1sec') |
| 207 | + }, 2000) |
| 208 | + proc.on('exit', () => { |
| 209 | + clearTimeout(timeoutKill) |
| 210 | + torDaemon.kill() |
| 211 | + callback() |
| 212 | + }) |
| 213 | + }) |
| 214 | + }, 500) |
| 215 | + }) |
| 216 | + /* eslint-enable no-unreachable */ |
| 217 | + }) |
80 | 218 | })
|
0 commit comments