test-download.js 6.2 KB

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