From 025e65a1a7562b02b0b576329466e3d42557c300 Mon Sep 17 00:00:00 2001 From: jianmosier <19506927+jianmosier@users.noreply.github.com> Date: Wed, 20 May 2026 20:20:13 +0800 Subject: [PATCH] test: cover trace tree binary search bounds --- test/binSearch.test.ts | 32 +++++++++++++++++++++++++++ ui/components/TreeNode.vue | 2 +- ui/src/binSearch.ts | 44 ++++++++++++++++---------------------- 3 files changed, 51 insertions(+), 27 deletions(-) create mode 100644 test/binSearch.test.ts diff --git a/test/binSearch.test.ts b/test/binSearch.test.ts new file mode 100644 index 0000000..d506022 --- /dev/null +++ b/test/binSearch.test.ts @@ -0,0 +1,32 @@ +import { describe, expect, it } from 'vitest' +import { binSearch } from '../ui/src/binSearch' + +describe('binSearch', () => { + const rows = [ + { ts: 10, label: 'a' }, + { ts: 20, label: 'b' }, + { ts: 30, label: 'c' }, + { ts: 40, label: 'd' }, + ] + + it('returns items inside the inclusive range', () => { + expect(binSearch(rows, 20, 30).map(row => row.label)).toEqual(['b', 'c']) + }) + + it('handles ranges that start before or end after the array', () => { + expect(binSearch(rows, 0, 20).map(row => row.label)).toEqual(['a', 'b']) + expect(binSearch(rows, 30, 100).map(row => row.label)).toEqual(['c', 'd']) + }) + + it('returns an empty array when the range misses the array', () => { + expect(binSearch(rows, 0, 5)).toEqual([]) + expect(binSearch(rows, 45, 100)).toEqual([]) + }) + + it('handles empty, single-item, and invalid ranges', () => { + expect(binSearch([], 0, 100)).toEqual([]) + expect(binSearch([{ ts: 0 }], 0, 0)).toEqual([{ ts: 0 }]) + expect(binSearch([{ ts: 0 }], 1, 1)).toEqual([]) + expect(binSearch(rows, 30, 20)).toEqual([]) + }) +}) diff --git a/ui/components/TreeNode.vue b/ui/components/TreeNode.vue index 997a094..13660c3 100644 --- a/ui/components/TreeNode.vue +++ b/ui/components/TreeNode.vue @@ -22,7 +22,7 @@ function fetchTypes() { function gotoPosition() { if ('name' in props.tree.line) { const { path, pos } = props.tree.line.args ?? { path: undefined, pos: undefined } - if (!path || !pos) + if (!path || pos === undefined) return sendMessage('gotoPosition', { fileName: path, pos }) diff --git a/ui/src/binSearch.ts b/ui/src/binSearch.ts index 7e60b01..683626e 100644 --- a/ui/src/binSearch.ts +++ b/ui/src/binSearch.ts @@ -1,37 +1,29 @@ // arr must be sorted by ts export function binSearch(arr: T[], from: number, to: number): T[] { if (arr.length === 0 || from > to) - return arr + return [] - let idx = Math.trunc(arr.length / 2) - let upperBound = arr.length - let lowerBound = 0 + let start = 0 + let end = arr.length - while (arr[idx].ts <= to) { - upperBound = idx - idx = Math.trunc(idx / 2) + while (start < end) { + const mid = Math.trunc((start + end) / 2) + if (arr[mid].ts < from) + start = mid + 1 + else + end = mid } - while (arr[idx].ts > to) { - lowerBound = idx - idx = Math.round(idx + (upperBound - idx) / 2) - } - - const endPos = lowerBound + const startPos = start - upperBound = lowerBound - lowerBound = 0 - while (arr[idx].ts > from) { - lowerBound = idx - idx = Math.round(idx + (upperBound - idx) / 2) + end = arr.length + while (start < end) { + const mid = Math.trunc((start + end) / 2) + if (arr[mid].ts <= to) + start = mid + 1 + else + end = mid } - while (arr[idx].ts <= from) { - upperBound = idx - idx = Math.trunc(idx / 2) - } - - const startPos = upperBound - - return arr.slice(startPos, endPos + 1) + return arr.slice(startPos, start) }