test-download.js 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  1. 'use strict'
  2. const { test } = require('tap')
  3. const fs = require('fs')
  4. const path = require('path')
  5. const util = require('util')
  6. const http = require('http')
  7. const https = require('https')
  8. const install = require('../lib/install')
  9. const semver = require('semver')
  10. const devDir = require('./common').devDir()
  11. const rimraf = require('rimraf')
  12. const gyp = require('../lib/node-gyp')
  13. const log = require('npmlog')
  14. const certs = require('./fixtures/certs')
  15. log.level = 'warn'
  16. test('download over http', async (t) => {
  17. t.plan(2)
  18. const server = http.createServer((req, res) => {
  19. t.strictEqual(req.headers['user-agent'], `node-gyp v42 (node ${process.version})`)
  20. res.end('ok')
  21. })
  22. t.tearDown(() => new Promise((resolve) => server.close(resolve)))
  23. const host = 'localhost'
  24. await new Promise((resolve) => server.listen(0, host, resolve))
  25. const { port } = server.address()
  26. const gyp = {
  27. opts: {},
  28. version: '42'
  29. }
  30. const url = `http://${host}:${port}`
  31. const res = await install.test.download(gyp, url)
  32. t.strictEqual(await res.text(), 'ok')
  33. })
  34. test('download over https with custom ca', async (t) => {
  35. t.plan(3)
  36. const cafile = path.join(__dirname, 'fixtures/ca.crt')
  37. const cacontents = certs['ca.crt']
  38. const cert = certs['server.crt']
  39. const key = certs['server.key']
  40. await fs.promises.writeFile(cafile, cacontents, 'utf8')
  41. const ca = await install.test.readCAFile(cafile)
  42. t.strictEqual(ca.length, 1)
  43. const options = { ca: ca, cert: cert, key: key }
  44. const server = https.createServer(options, (req, res) => {
  45. t.strictEqual(req.headers['user-agent'], `node-gyp v42 (node ${process.version})`)
  46. res.end('ok')
  47. })
  48. t.tearDown(async () => {
  49. await new Promise((resolve) => server.close(resolve))
  50. await fs.promises.unlink(cafile)
  51. })
  52. server.on('clientError', (err) => { throw err })
  53. const host = 'localhost'
  54. await new Promise((resolve) => server.listen(0, host, resolve))
  55. const { port } = server.address()
  56. const gyp = {
  57. opts: { cafile },
  58. version: '42'
  59. }
  60. const url = `https://${host}:${port}`
  61. const res = await install.test.download(gyp, url)
  62. t.strictEqual(await res.text(), 'ok')
  63. })
  64. test('download over http with proxy', async (t) => {
  65. t.plan(2)
  66. const server = http.createServer((_, res) => {
  67. res.end('ok')
  68. })
  69. const pserver = http.createServer((req, res) => {
  70. t.strictEqual(req.headers['user-agent'], `node-gyp v42 (node ${process.version})`)
  71. res.end('proxy ok')
  72. })
  73. t.tearDown(() => Promise.all([
  74. new Promise((resolve) => server.close(resolve)),
  75. new Promise((resolve) => pserver.close(resolve))
  76. ]))
  77. const host = 'localhost'
  78. await new Promise((resolve) => server.listen(0, host, resolve))
  79. const { port } = server.address()
  80. await new Promise((resolve) => pserver.listen(port + 1, host, resolve))
  81. const gyp = {
  82. opts: {
  83. proxy: `http://${host}:${port + 1}`,
  84. noproxy: 'bad'
  85. },
  86. version: '42'
  87. }
  88. const url = `http://${host}:${port}`
  89. const res = await install.test.download(gyp, url)
  90. t.strictEqual(await res.text(), 'proxy ok')
  91. })
  92. test('download over http with noproxy', async (t) => {
  93. t.plan(2)
  94. const server = http.createServer((req, res) => {
  95. t.strictEqual(req.headers['user-agent'], `node-gyp v42 (node ${process.version})`)
  96. res.end('ok')
  97. })
  98. const pserver = http.createServer((_, res) => {
  99. res.end('proxy ok')
  100. })
  101. t.tearDown(() => Promise.all([
  102. new Promise((resolve) => server.close(resolve)),
  103. new Promise((resolve) => pserver.close(resolve))
  104. ]))
  105. const host = 'localhost'
  106. await new Promise((resolve) => server.listen(0, host, resolve))
  107. const { port } = server.address()
  108. await new Promise((resolve) => pserver.listen(port + 1, host, resolve))
  109. const gyp = {
  110. opts: {
  111. proxy: `http://${host}:${port + 1}`,
  112. noproxy: host
  113. },
  114. version: '42'
  115. }
  116. const url = `http://${host}:${port}`
  117. const res = await install.test.download(gyp, url)
  118. t.strictEqual(await res.text(), 'ok')
  119. })
  120. test('download with missing cafile', async (t) => {
  121. t.plan(1)
  122. const gyp = {
  123. opts: { cafile: 'no.such.file' }
  124. }
  125. try {
  126. await install.test.download(gyp, {}, 'http://bad/')
  127. } catch (e) {
  128. t.ok(/no.such.file/.test(e.message))
  129. }
  130. })
  131. test('check certificate splitting', async (t) => {
  132. const cafile = path.join(__dirname, 'fixtures/ca-bundle.crt')
  133. const cacontents = certs['ca-bundle.crt']
  134. await fs.promises.writeFile(cafile, cacontents, 'utf8')
  135. t.tearDown(async () => {
  136. await fs.promises.unlink(cafile)
  137. })
  138. const cas = await install.test.readCAFile(path.join(__dirname, 'fixtures/ca-bundle.crt'))
  139. t.plan(2)
  140. t.strictEqual(cas.length, 2)
  141. t.notStrictEqual(cas[0], cas[1])
  142. })
  143. // only run this test if we are running a version of Node with predictable version path behavior
  144. test('download headers (actual)', async (t) => {
  145. if (process.env.FAST_TEST ||
  146. process.release.name !== 'node' ||
  147. semver.prerelease(process.version) !== null ||
  148. semver.satisfies(process.version, '<10')) {
  149. return t.skip('Skipping actual download of headers due to test environment configuration')
  150. }
  151. t.plan(12)
  152. const expectedDir = path.join(devDir, process.version.replace(/^v/, ''))
  153. await util.promisify(rimraf)(expectedDir)
  154. const prog = gyp()
  155. prog.parseArgv([])
  156. prog.devDir = devDir
  157. log.level = 'warn'
  158. await util.promisify(install)(prog, [])
  159. const data = await fs.promises.readFile(path.join(expectedDir, 'installVersion'), 'utf8')
  160. t.strictEqual(data, '9\n', 'correct installVersion')
  161. const list = await fs.promises.readdir(path.join(expectedDir, 'include/node'))
  162. t.ok(list.includes('common.gypi'))
  163. t.ok(list.includes('config.gypi'))
  164. t.ok(list.includes('node.h'))
  165. t.ok(list.includes('node_version.h'))
  166. t.ok(list.includes('openssl'))
  167. t.ok(list.includes('uv'))
  168. t.ok(list.includes('uv.h'))
  169. t.ok(list.includes('v8-platform.h'))
  170. t.ok(list.includes('v8.h'))
  171. t.ok(list.includes('zlib.h'))
  172. const lines = (await fs.promises.readFile(path.join(expectedDir, 'include/node/node_version.h'), 'utf8')).split('\n')
  173. // extract the 3 version parts from the defines to build a valid version string and
  174. // and check them against our current env version
  175. const version = ['major', 'minor', 'patch'].reduce((version, type) => {
  176. const re = new RegExp(`^#define\\sNODE_${type.toUpperCase()}_VERSION`)
  177. const line = lines.find((l) => re.test(l))
  178. const i = line ? parseInt(line.replace(/^[^0-9]+([0-9]+).*$/, '$1'), 10) : 'ERROR'
  179. return `${version}${type !== 'major' ? '.' : 'v'}${i}`
  180. }, '')
  181. t.strictEqual(version, process.version)
  182. })