Skip to content

test: restore latest Bun coverage and preserve sparse values - #803

Merged
owjs3901 merged 3 commits into
mainfrom
test/bun-latest-coverage
Oct 23, 2026
Merged

owjs3901 merged 3 commits into
mainfrom
test/bun-latest-coverage

Conversation

@owjs3901

@owjs3901 owjs3901 commented Oct 22, 2026 •

Copy link
Copy Markdown
Contributor

Refs #683 (최신 Bun 커버리지 게이트 복구). main의 78d7c2b2에서 직접 분기했으며 선행 PR은 없습니다. #791의 브랜치와 PR은 변경하지 않았습니다.

교정 및 CI

검토에서 확인한 괄호 경계 손상과 정규식/null 오인은 승인된 세 번째 커밋 968f0d36에서 수정했습니다. 새 트리는 두 Bun 버전에서 6857개 테스트와 커버리지 100/100, 실제 source/배포 산출물 각각 3212개 입력의 parser·기대 출력·작성된 값 바이트 보존 검사를 통과했습니다. 새 head의 CI 39909630698는 8개 필수 validation job 모두 성공했으며 재실행은 필요하지 않았습니다. 이전 head의 취소된 CI를 새 트리의 성공 증거로 사용하지 않습니다.

요약

Bun 1.4.4에서 새로 드러난 main 자체의 테스트 누락을 실제 입력과 공개 동작으로 보완합니다. 버전 고정, 커버리지 제외, 임계값 완화, ignore 주석 없이 함수/줄 커버리지 100.00 / 100.00을 복구합니다.

커밋은 세 개로 분리했습니다. c59d5064는 기존 동작을 보존하는 커버리지 복구, c1295d88은 별도로 승인받은 희소 배열 자동 수정, 968f0d36은 검토에서 확인한 괄호/주석 경계와 canonical null 판별 교정입니다. 세 번째 전체 hook과 두 번째 push도 별도 승인 후 실행했습니다. 스타일 런타임, 의존성, 생성 CSS/클래스 이름, Rust 코드는 추가하거나 변경하지 않았습니다.

동작

같은 main 소스/빌드 산출물로 두 Bun 버전을 비교했습니다.

트리 Bun 통과/실패 All files 함수 All files 줄 LCOV 미실행 줄
변경 전 main 78d7c2b2 1.4.3+c6da4a4d3 6654 / 0 100.00 100.00 0
변경 전 main 78d7c2b2 1.4.4+38afee6c8 6654 / 0 100.00 99.91 29
커버리지 복구 c59d5064 1.4.3+c6da4a4d3 6692 / 0 100.00 100.00 0
커버리지 복구 c59d5064 1.4.4+38afee6c8 6692 / 0 100.00 100.00 0
희소 기본 수정 c1295d88 1.4.3+c6da4a4d3 6705 / 0 100.00 100.00 0
희소 기본 수정 c1295d88 1.4.4+38afee6c8 6705 / 0 100.00 100.00 0
최종 교정 968f0d36 1.4.3+c6da4a4d3 6857 / 0 100.00 100.00 0
최종 교정 968f0d36 1.4.4+38afee6c8 6857 / 0 100.00 100.00 0

29줄의 위치는 변경 전 main 기준입니다. 실제 도달 가능한 28줄은 추가한 사례로 실행되며, 나머지 한 줄은 아래 증명에 따라 불가능한 분기를 없앴습니다.

소스 (packages/ 아래) 이전 미실행 줄 첫 복구 커밋의 결과
eslint-plugin/src/rules/css-utils-literal-only/index.ts 276–278, 317, 319–320, 523, 598–601, 939–942, 944–945, 1129 각 줄의 DA > 0
eslint-plugin/src/rules/no-useless-tailing-nulls/index.ts 34 실제 AST로 도달 불가능한 return 제거
eslint-plugin/src/utils/style-position.ts 599 DA > 0
next-plugin/src/coordinator-port.ts 73 DA > 0
next-plugin/src/wasm.ts 29 DA > 0
plugin-utils/src/import-graph.ts 633 DA > 0
plugin-utils/src/reservation-discovery.ts 109 DA > 0
react/src/stores/theme-store.ts 47 부모 프로세스 LCOV에서 DA > 0
webpack-plugin/src/plugin.ts 108, 166–168 각 줄의 DA > 0

추가한 실제 동작 사례

  • CSS literal 규칙: 따옴표 p 구조분해 허용, 따옴표 normalize 구조분해 거부, 상수 계산 키 구조분해 허용.
  • 배열 멤버 escape: 원시값 고정 인덱스와 범위 밖 인덱스는 상수를 오염시키지 않음; 객체 요소 escape와 spread holder의 불확실한 escape는 거부.
  • 배열 wrapper: 알 수 없는 unknown([L]) 소비자는 거부; 변경되지 않는 exported const [L]은 허용.
  • CommonJS export: module.exports.token=L, module['exports'].token=L 허용; other.exports.token=L은 escape로 거부.
  • 순수 함수: 모듈 data const 읽기, const arrow helper 호출, const function-expression helper 호출 허용; Date.now() helper와 모듈 class 바인딩 읽기는 거부.
  • 실제 문자열 이름 StyleX import (import { 'create' as create } ...): literal width 허용, runtime width 진단 유지.
  • 실제 parser/context의 공개 styleValueSite: css/styled callee와 styled Base 인자는 스타일이 아니며, 선택된 규칙 인자는 정확한 style site를 가짐.
  • 첫 실행의 존재하지 않는 coordinator port 파일 정리는 throw하지 않음.
  • 설치/워크스페이스 plugin manifest가 없는 프로젝트에서도 root manifest를 기준으로 실제 CJS 의존성을 해석.
  • 실제 파일을 source root로 주었을 때 ENOTDIR를 전달하고, error handler가 처리를 거절하면 받은 오류 객체 자체를 다시 throw.
  • 기본 tsconfig가 wrong.ts, 명시한 상대 경로 tsconfig가 right.ts를 가리키는 서로 다른 fixture에서 right.ts만 예약 목록에 포함.
  • Webpack 생성자의 무인자 호출과 {} 호출 모두 기존 기본 옵션 유지.
  • 실제 디렉터리를 설정 파일 경로로 주어 읽기에 실패하면 실제 WASM 테마를 비우고 오류를 기록한 뒤 CSS 디렉터리 생성까지 계속 진행. 파일 시스템/설정 로더를 mock하지 않음.
  • DOM이 없는 환경을 복원 가능한 descriptor로 구성하고 실제 모듈을 새로 평가하여 SSR factory 선택, null 읽기, inert set, 알림 없는 구독/해제를 확인. 별도 자식 프로세스 커버리지를 부모 커버리지로 간주하지 않음.
  • trailing-null 규칙은 먼저 기존 구현에서 빈 배열, 홀, 모든 null, 혼합 배열의 진단/수정 결과를 특성화한 뒤 분기만 좁힘. 341개 배열을 css/JSX 두 문맥에서 비교한 총 682개 실제 Linter 입력은 첫 커밋에서 main과 결과가 모두 같았음.

도달 불가능한 분기의 증명

기존 역방향 scan은 실제로 존재하는 Literal(value=null) 노드만 셉니다. nullCount > 0이면 마지막 원소는 반드시 존재하며, nullCount === elements.length이면 첫 원소도 반드시 존재합니다. scan과 검사 사이에 AST를 바꾸는 코드가 없으므로 그 뒤의 !lastElement || (allNull && !firstElement) return은 실제 parser AST에서 실행될 수 없습니다.

마지막 원소가 Literal-null인지 먼저 좁힌 후 나머지를 scan하도록 바꿨습니다. 빈 배열/마지막 홀/마지막 비-null은 같은 경로로 빠져나오며, 가짜 AST나 getter를 만들어 불가능한 상태를 실행하지 않았습니다. 첫 커밋은 기존 sparse 보호/수정 범위도 그대로 보존했고, 이후의 동작 변경은 아래 별도 버그 수정 커밋에만 있습니다.

희소 배열 자동 수정 버그

기존 규칙은 [1,,null]을 []로 고쳐 작성된 1까지 삭제했습니다. 마지막 원소가 Literal-null일 때만 보고한다는 조건과 메시지는 유지하고, 그 앞의 연속된 null/홀 suffix만 제거하도록 승인된 범위를 수정합니다. 그보다 앞의 작성된 값과 내부/선행 홀은 보존합니다.

아래 모든 입력은 실제 RuleTester로 실행했습니다. 0 / 유지는 진단과 수정 없음, 1 / 결과는 기존 uselessTailingNulls 진단 한 개와 최종 수정 결과입니다.

입력 배열 수정 전 진단 / 결과 수정 후 진단 / 결과
[] 0 / 유지 0 / 유지
[,] 0 / 유지 0 / 유지
[1,null,,] 0 / 유지 0 / 유지
[null,,] 0 / 유지 0 / 유지
[,,] 0 / 유지 0 / 유지
[1,,] 0 / 유지 0 / 유지
[1,,2] 0 / 유지 0 / 유지
[1, null, 2] 0 / 유지 0 / 유지
[null] 1 / [] 1 / []
[null,null] 1 / [] 1 / []
[1,null] 1 / [1] 1 / [1]
[1,,null] 1 / [] 1 / [1]
[,1,null] 1 / [,1] 1 / [,1]
[1,,2,null] 1 / [1,,2] 1 / [1,,2]
[1,,null,null] 1 / [] 1 / [1]
[,null] 0 / 유지 1 / []
[,,null,null] 0 / 유지 1 / []
[/* keep */ null,null] 1 / [/* keep */ ] 1 / [/* keep */ ]
[1,null,,null] 1 / [] 1 / [1]
[null,1,,null] 1 / [] 1 / [null,1]
[value,,null] 1 / [] 1 / [value]
[...values,,null] 1 / [] 1 / [...values]

수정 전 RED는 26개 통과/8개 실패, 수정 후 GREEN은 34개 통과/0개 실패입니다. 해당 규칙의 LCOV는 함수 6/6, 줄 60/60입니다. 별도 실제 Linter 드라이버의 css/JSX 682개 입력도 승인된 suffix 규칙과 모두 일치하며, 이전 구현과의 차이는 의도한 46개뿐입니다. 최종 빌드된 공개 rule export에도 같은 682개 입력을 실행해 모두 확인했습니다. 한 번의 역방향 scan이며 O(n) 시간/O(1) 추가 공간입니다.

괄호·주석·후행 쉼표 경계 교정

AST는 괄호 wrapper를 생략할 수 있어 내부 노드의 range만 쓰면 닫는 괄호를 지우거나 제거할 null의 괄호를 남겼습니다. 실제 ESLint 토큰으로 유지할 완전한 표현식의 끝과 제거할 완전한 표현식의 끝을 찾습니다. 문자열 slicing이나 정규식 기반 소스 재작성은 사용하지 않습니다. 토큰 조회는 fix callback에서만 수행하며, 전체 token 배열을 복사하지 않고 고정 개수만 조회합니다.

아래 각 행은 CSS/JSX 두 문맥에서 실제 RuleTester와 별도 Linter/parser 검사로 실행했습니다. !는 수정 결과에 parser 오류가 있음을 뜻합니다. 괄호, 주석, 표기, 내부 공백을 포함한 전체 기대 문자열을 독립적으로 작성해 실제 출력과 바이트 단위로 비교했습니다.

입력 원본 main 결과 c1295d88 결과 최종 결과
[0,(1),,null] [] [0,(1] ! [0,(1)]
[0,((1)),,null] [] [0,((1] ! [0,((1))]
[0,(1),null] [0,(1] ! [0,(1] ! [0,(1)]
[0,(1),,(null)] [)] ! [0,(1)] [0,(1)]
[(null)] [()] ! [()] ! []
[1,null] [1] [1] [1]
[0,((1)),,((null))] [))] ! [0,((1))] [0,((1))]
[((null)),(null)] [(()] ! [(()] ! []
[0,( /* value */ 1 /* inner */ ), /* remove */ , (null)] [)] ! [0,( /* value */ 1)] [0,( /* value */ 1 /* inner */ )]
[1 /* remove */, /* remove */ null /* keep */] [1 /* keep */] 동일 동일
[/* keep */ (null),null] [/* keep */ (] ! 동일 ! [/* keep */ ]
[, /* remove */ (null)] 진단 없음 [)] ! []
[0,(1),null,] [0,(1,] ! 동일 ! [0,(1),]
[0,((1)),,((null)),] [)),] ! [0,((1)),] [0,((1)),]
[(null),] [(),] ! 동일 ! [,]
[null,] [,] 동일 동일
[1,null, /* keep */] [1, /* keep */] 동일 동일
[1,null /* keep */,] [1 /* keep */,] 동일 동일
[0,(1), /* remove */ null /* keep */, /* tail */] [0,(1 /* keep */, /* tail */] ! 동일 ! [0,(1) /* keep */, /* tail */]
[/* keep */ ((null)) /* tail */] [/* keep */ (()) /* tail */] ! 동일 ! [/* keep */ /* tail */]

같은 40개 입력을 원본 main에서 한 번 실행했습니다. main은 parser 오류 24개, c1295d88은 parser 오류 22개와 작성된 내부 주석/공백 손실 2개였으며, 교정 후 40개 모두 기대 문자열과 일치하고 parser 검사를 통과합니다. c1295d88의 parser 오류 중 16개는 main부터 존재했고, 6개(첫 두 행과 [, /* remove */ (null)], 각 CSS/JSX)는 희소 수정에서 새로 생긴 오류였습니다. 경계 수정 RED 66통과/48실패 → GREEN 114통과/0실패입니다.

Canonical null 및 정규식 보존

실제 TypeScript-ESLint 파서는 malformed regex의 AST를 Literal이면서 value:null, regex 메타데이터가 있는 형태로 줄 수 있습니다. main은 이를 null로 오인해 작성된 정규식을 삭제했습니다. 승인된 canonical 술어 Literal && raw === 'null' 하나를 진단 조건과 suffix scan에서 공통 사용합니다. 정규식 유효성 판정 자체는 기존 소유자에게 남기며, 이 규칙은 regex/BigInt 구문을 그대로 보존합니다.

아래는 새 입력만 원본 main으로 한 번 실행한 결과입니다. 각 행은 CSS/JSX 두 문맥에서 실행했습니다. 0 / 유지는 진단/수정 없음입니다.

입력 main 진단 / 결과 최종 진단 / 결과
[/(/,null] 1 / [] 1 / [/(/]
[/a/gg,null] 1 / [] 1 / [/a/gg]
[/a/z,null] 1 / [] 1 / [/a/z]
[/a/gg,,null] 1 / [] 1 / [/a/gg]
[/a/g,null] 1 / [/a/g] 동일
[/a/g,,null] 1 / [] 1 / [/a/g]
[(/(/),,(null)] 1 / [()] 1 / [(/(/)]
[1n,null] 1 / [1n] 동일
[0xFFn,,null] 1 / [] 1 / [0xFFn]
[1n,null,,(null),] 1 / [),] 1 / [1n,]
[/(/] 1 / [] 0 / 유지
[/a/gg] 1 / [] 0 / 유지
[/a/z] 1 / [] 0 / 유지
[1,null,/(/] 1 / [1] 0 / 유지
[/a/g] 0 / 유지 동일
[1n] 0 / 유지 동일
[0xFFn] 0 / 유지 동일
[null,1n] 0 / 유지 동일

36개 새 입력 중 canonical 판별로 수정한 18개는 모두 main부터 실패하던 사례입니다. real RED 150통과/36실패 → GREEN 186통과/0실패이며 이전 114개도 모두 유지됩니다. 최종 해당 규칙 커버리지는 함수 7/7·줄 71/71(100/100), 두 변경 TS 파일의 strict no-emit 타입 검사와 lint도 통과했습니다. malformed regex를 보존한 출력의 parser 통과는 TypeScript-ESLint parser 기준이며, 잘못된 정규식을 JS 엔진에서 유효한 것으로 판정한다는 뜻은 아닙니다.

원본 main은 실제 git object에서 읽은 코드에 import 경로만 재배치해 로드했고, 역치환한 원문 SHA256(c31004e613c10069a73cadd92b19ad8a22ccbc231db94f023c473214595d1d11) 동일성과 사용 utility의 main 동일성을 확인했습니다. 가짜 이전 구현이나 AST를 만들지 않았고, 이전 40개 입력을 새 36개 batch에서 재실행하지 않았습니다.

독립 부모 드라이버도 source 및 새로 빌드된 공개 rule export에 각각 3212개 입력을 실행했습니다. 괄호 깊이, 선행/중간 홀, 주석, 후행 쉼표, regex/BigInt와 다중 바이트 작성 값까지 기대 출력·parser 통과·비-null 값의 원문 보존을 모두 확인했으며 두 산출물의 결과 hash가 같습니다.

새로 생기는 오류

새 빌드 오류는 없습니다. trailing-null 규칙의 메시지는 그대로입니다. 마지막이 null인 [,null], [,,null,null]은 이제 같은 기존 메시지로 보고되고 []로 자동 수정됩니다.

남는 한계

마지막 원소가 홀인 배열은 기존처럼 보고하지 않으며, [null,] -> [,]처럼 기존 후행 쉼표 정책도 유지합니다. 정규식 검증은 이 규칙에 추가하지 않았습니다. #802 트리에만 있는 build ownership 초기화 및 Vite lane 변경은 이 main 기반 PR의 범위가 아닙니다. 커버리지와 승인된 자동 수정 교정 외의 제품 동작은 변경하지 않았습니다.

검증

  • 공식 Bun 1.4.4 Windows release archive의 SHA256을 공식 SHASUMS256.txt 및 release digest와 대조: cd2c0fccc78f3ede1f50ca827a15f063eda13d4d150a3d0674f4f6e323d864a5. private temp에만 두었으며 공유 Bun 1.4.3 설치는 변경하지 않음.
  • fresh install → WASM build → root build. 최종 root build 및 두 Bun 버전의 실제 All files 행과 LCOV 확인.
  • 최종 bun run test 통과: private Bun 1.4.4에서 6857개 통과/0개 실패, All files 함수/줄 100.00/100.00, LCOV 미실행 줄 0. 공유 Bun 1.4.3의 독립 bun test --coverage도 동일.
  • 최종 bun lint 통과: fmt/strict clippy 포함, ESLint 오류 0. 변경하지 않은 기존 React 파일의 경고 20개는 그대로이며 새 경고 없음.
  • 로컬 Windows tarpaulin은 23505/23892줄(98.38%)이며 Rust 소스 변경은 없음. Linux CI publish에서는 strict 100% 게이트(16602/16602줄)를 통과했습니다.
  • 승인된 세 커밋 각각 전체 pre-commit hook을 한 번씩 통과했고, 각 hook이 검사한 정확한 트리를 whole-file stage로 커밋. 최초 두 커밋의 첫 push와 승인된 교정 커밋의 두 번째 push만 실행했습니다. 빌드/테스트 6 GiB, hook 12 GiB native job 제한, 시작 전 7 GiB 여유 메모리 검사, CARGO_BUILD_JOBS=2, CI unset, 기본 Rust stack 유지.
  • TypeScript LSP는 설치되어 있지 않아 진단 성공으로 주장하지 않음. 실제 빌드와 정상 TypeScript6 preload를 사용하는 ESLint로 검증.
  • CI 39808681150의 publish 로그: bun install v1.4.4 (38afee6c8), bun test v1.4.4, All files | 100.00 | 100.00, 6705 pass/0 fail. Rust 16602/16602줄(100.00%), preload 회귀 10개, landing E2E 190개와 singleCss E2E 190개도 통과했습니다.
  • 기존 head의 validation job 7개(publish, benchmark, react-18, wasm-size, webpack-extends-theme, vinext-rsc-css-e2e, landing-next-e2e)는 성공했습니다. release-compat만 Playwright 의존성 설치 중 azure.archive.ubuntu.com의 apt 다운로드가 지연되어 30분 job 제한으로 취소되었고 consumer 테스트에는 도달하지 못했습니다. 구문 경계 교정 후 새 head에서 CI를 다시 실행하므로 이 이전 head의 job만 재실행하지 않습니다. 전체 CI 성공으로 주장하지 않으며, PR에서 의도적으로 실행하지 않는 deploy-pages/release job의 skip과는 구분합니다.
  • 최종 head 968f0d362c7c3683713c7144bdf338b614e9b316의 새 CI 39909630698 성공: publish, benchmark, react-18, wasm-size, webpack-extends-theme, vinext-rsc-css-e2e, release-compat, landing-next-e2e 모두 성공. 재실행 0회이며 PR 전용 조건으로 배포/릴리스 job이 skip되는 것은 정상입니다.
  • 최종 publish 로그에 실제 bun install v1.4.4 (38afee6c8)와 bun test v1.4.4, 6857 pass/0 fail, All files | 100.00 | 100.00, Rust 16602/16602줄(100.00%)이 출력되었습니다. preload 회귀 10개와 landing 190개/190개 E2E도 통과했습니다.
  • Vinext per-file/singleCss 각각 29개 테스트 통과, 각각 6 routes prerendered/0 skipped입니다. release-compat은 Vite/Rsbuild/Webpack/Next Webpack/Next Turbopack의 두 CSS 모드 모두 실제 production artifact 검사를 실행했고 Chromium/Firefox/WebKit의 computed styles/runtime 검사까지 통과했습니다.

owjs3901 and others added 2 commits October 22, 2026 23:59
Refs #683

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Refs #683

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
@codecov

codecov Bot commented Oct 22, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

Files with missing lines Coverage Δ
...plugin/src/rules/no-useless-tailing-nulls/index.ts 100.00% <100.00%> (ø)

... and 84 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Refs #683

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
@owjs3901
owjs3901 merged commit a31c419 into main Oct 23, 2026
11 checks passed
@owjs3901
owjs3901 deleted the test/bun-latest-coverage branch October 23, 2026 11:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant