serviceInstance.test.ts 2.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344
  1. // @vitest-environment node
  2. import { afterEach, beforeEach, describe, expect, it } from 'vitest'
  3. import { mkdtempSync, readFileSync, rmSync } from 'node:fs'
  4. import { tmpdir } from 'node:os'
  5. import { join } from 'node:path'
  6. import Koa from 'koa'
  7. import request from 'supertest'
  8. import { acquireServiceInstance } from '../../src/server/serviceInstance'
  9. let home: string
  10. let instances: ReturnType<typeof acquireServiceInstance>[]
  11. beforeEach(() => { home = mkdtempSync(join(tmpdir(), 'yaoyao-service-lock-')); instances = [] })
  12. afterEach(() => { for (const instance of instances) instance.release(); rmSync(home, { recursive: true, force: true }) })
  13. const acquire = (desktop = true) => { const instance = acquireServiceInstance(home, '0.3.32', desktop); instances.push(instance); return instance }
  14. describe('service ownership', () => {
  15. it('excludes a second process connection and releases ownership explicitly', () => {
  16. const first = acquire()
  17. expect(() => acquire()).toThrow('另一个')
  18. first.release()
  19. const next = acquire()
  20. expect(next.record.instanceId).not.toBe(first.record.instanceId)
  21. first.release()
  22. expect(JSON.parse(readFileSync(join(home, 'service-instance.json'), 'utf8')).instanceId).toBe(next.record.instanceId)
  23. })
  24. it('uses a private capability and exact local service identity, not a public port probe', async () => {
  25. const instance = acquire();instance.publish('http://127.0.0.1:12345')
  26. let stops = 0
  27. const app = new Koa().use(instance.middleware(async () => { stops++ }))
  28. await request(app.callback()).get('/desktop/service').expect(403)
  29. await request(app.callback()).get('/desktop/service').set('x-yaoyao-desktop-token', instance.record.token).set('Origin', 'http://evil.test').expect(403)
  30. const result = await request(app.callback()).get('/desktop/service').set('x-yaoyao-desktop-token', instance.record.token).expect(200)
  31. expect(result.body).toMatchObject({ protocol: 1, pid: process.pid, instanceId: instance.record.instanceId })
  32. expect(result.body.token).toBeUndefined()
  33. await request(app.callback()).delete('/desktop/service').set('x-yaoyao-desktop-token', instance.record.token).expect(200)
  34. await new Promise(resolve => setImmediate(resolve))
  35. expect(stops).toBe(1)
  36. })
  37. it('refuses stopping an externally managed CLI service', async () => {
  38. const instance = acquire(false)
  39. const app = new Koa().use(instance.middleware(async () => { throw new Error('must not stop') }))
  40. await request(app.callback()).delete('/desktop/service').set('x-yaoyao-desktop-token', instance.record.token).expect(405)
  41. })
  42. })