test-water-driving.mjs 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  1. import assert from 'node:assert/strict'
  2. import { readFile } from 'node:fs/promises'
  3. import ts from 'typescript'
  4. // Isolate the provider contract without accessing a browser, a key or live orders.
  5. const calls = []
  6. const policies = []
  7. let response
  8. let now = 100000
  9. const requestedAt = []
  10. Date.now = () => now
  11. globalThis.window = {
  12. setTimeout: (callback, ms) => {
  13. if (ms < 10000) {
  14. now += ms
  15. return setTimeout(callback, 0)
  16. }
  17. return setTimeout(callback, ms)
  18. },
  19. AMap: {
  20. plugin: (_plugins, done) => done(),
  21. Driving: class {
  22. constructor(options) {
  23. policies.push(options.policy)
  24. }
  25. search(start, end, options, done) {
  26. calls.push([start, ...options.waypoints, end])
  27. requestedAt.push(now)
  28. response(done)
  29. }
  30. }
  31. }
  32. }
  33. const source = await readFile(new URL('../src/utils/waterAmap.ts', import.meta.url), 'utf8')
  34. const { outputText } = ts.transpileModule(source, {
  35. compilerOptions: { target: ts.ScriptTarget.ES2022, module: ts.ModuleKind.ESNext }
  36. })
  37. const { planWaterDriving, collectWaterRoadMatrix } = await import(
  38. `data:text/javascript;base64,${Buffer.from(outputText).toString('base64')}`
  39. )
  40. const success = (done) =>
  41. done('complete', {
  42. routes: [
  43. {
  44. distance: 1000,
  45. time: 60,
  46. steps: [
  47. {
  48. path: [
  49. [113, 22],
  50. [114, 23]
  51. ]
  52. }
  53. ]
  54. }
  55. ]
  56. })
  57. response = success
  58. const stops = Array.from({ length: 37 }, (_, i) => [113 + i / 1000, 22])
  59. const result = await planWaterDriving(stops, () => true)
  60. assert.equal(calls.length, 3)
  61. assert.ok(calls.every((chunk) => chunk.length <= 18))
  62. assert.deepEqual([calls[0][0], ...calls.flatMap((chunk) => chunk.slice(1))], stops)
  63. assert.equal(result.distance, 3000)
  64. assert.equal(result.time, 180)
  65. calls.length = 0
  66. await planWaterDriving([stops[0], stops[0], stops[1], stops[1]], () => true)
  67. assert.deepEqual(calls, [[stops[0], stops[1]]])
  68. calls.length = 0
  69. assert.equal((await planWaterDriving([stops[0], stops[0]], () => true)).distance, 0)
  70. assert.equal(calls.length, 0)
  71. let active = true
  72. response = (done) => {
  73. active = false
  74. success(done)
  75. }
  76. assert.equal(await planWaterDriving(stops, () => active), undefined)
  77. assert.equal(calls.length, 1)
  78. calls.length = 0
  79. assert.equal(await planWaterDriving(stops, () => false), undefined)
  80. assert.equal(calls.length, 0)
  81. response = (done) => (calls.length === 1 ? success(done) : done('error', 'OVER_QUOTA'))
  82. await assert.rejects(
  83. planWaterDriving(stops, () => true),
  84. /OVER_QUOTA/
  85. )
  86. assert.equal(calls.length, 2)
  87. response = (done) => done('complete', { routes: [{ distance: 1, time: 1, steps: [] }] })
  88. await assert.rejects(
  89. planWaterDriving(stops.slice(0, 2), () => true),
  90. /未返回可用/
  91. )
  92. console.log(
  93. 'PASS: ordered chunking, totals, duplicate stops, same location, stale requests, partial failure, invalid paths'
  94. )
  95. calls.length = 0
  96. policies.length = 0
  97. response = success
  98. let progress
  99. const matrix = await collectWaterRoadMatrix(
  100. stops.slice(0, 3),
  101. 'shortest',
  102. () => true,
  103. (done, total) => {
  104. progress = [done, total]
  105. }
  106. )
  107. assert.deepEqual(progress, [6, 6])
  108. assert.equal(calls.length, 4)
  109. assert.ok(policies.every((value) => value === 2))
  110. assert.deepEqual(calls[2], [stops[1], stops[2]])
  111. assert.deepEqual(calls[3], [stops[2], stops[1]])
  112. assert.equal(matrix[1][0], null)
  113. assert.deepEqual(matrix[1][1], { distance: 0, time: 0 })
  114. calls.length = 0
  115. await collectWaterRoadMatrix(
  116. stops.slice(0, 3),
  117. 'shortest',
  118. () => true,
  119. () => {}
  120. )
  121. assert.equal(calls.length, 0, 'repeat directed matrix uses fresh shared cost cache')
  122. now += 60001
  123. await collectWaterRoadMatrix(
  124. stops.slice(0, 3),
  125. 'shortest',
  126. () => true,
  127. () => {}
  128. )
  129. assert.equal(calls.length, 4, 'expired road costs are refreshed')
  130. response = (done) => done('error', 'NO_DATA')
  131. const unreachable = await collectWaterRoadMatrix(
  132. stops.slice(0, 2),
  133. 'fastest',
  134. () => true,
  135. () => {}
  136. )
  137. assert.equal(unreachable[0][1], null)
  138. response = (done) => done('error', 'OVER_QUOTA')
  139. await assert.rejects(
  140. collectWaterRoadMatrix(
  141. stops.slice(0, 2),
  142. 'deadline',
  143. () => true,
  144. () => {}
  145. ),
  146. /OVER_QUOTA/
  147. )
  148. console.log(
  149. 'PASS: directed road matrix, shortest policy, progress, same-coordinate cells, unreachable roads and provider errors'
  150. )
  151. requestedAt.length = 0
  152. let attempts = 0
  153. response = (done) =>
  154. ++attempts < 3 ? done('error', 'CUQPS_HAS_EXCEEDED_THE_LIMIT') : success(done)
  155. await planWaterDriving(stops.slice(0, 2), () => true)
  156. assert.equal(attempts, 3)
  157. assert.ok(requestedAt[1] - requestedAt[0] >= 1500)
  158. assert.ok(requestedAt[2] - requestedAt[1] >= 3000)
  159. attempts = 0
  160. response = (done) => {
  161. attempts++
  162. done('error', 'CUQPS_HAS_EXCEEDED_THE_LIMIT')
  163. }
  164. await assert.rejects(
  165. planWaterDriving(stops.slice(0, 2), () => true),
  166. /请求过于频繁/
  167. )
  168. assert.equal(attempts, 3, 'QPS retry count is bounded')
  169. requestedAt.length = 0
  170. response = success
  171. await Promise.all([
  172. planWaterDriving(stops.slice(0, 2), () => true),
  173. planWaterDriving(stops.slice(1, 3), () => true)
  174. ])
  175. assert.ok(requestedAt[1] - requestedAt[0] >= 1100, 'concurrent planners share pacing')
  176. let current = true
  177. const cancelled = planWaterDriving(stops.slice(0, 2), () => current)
  178. current = false
  179. assert.equal(await cancelled, undefined, 'queued stale request never reaches provider')
  180. console.log('PASS: shared pacing, TTL cache, QPS backoff, bounded retries and queued cancellation')