본문으로 건너뛰기

CI 커버리지 & 실장 테스트 가이드

작성: 2026-06-04
목적: LMCache PR CI가 실제로 어디까지 검증하는지 정리하고, CI 사각지대에서 실장 테스트가 필수인 경우를 기록한다.


1. PR CI 구조 요약

모든 워크플로우는 .github/workflows/에 있으며, dorny/paths-filter로 변경 경로를 감지해서 관련 있을 때만 job을 실행한다.

PR마다 자동으로 도는 것 (draft 포함)

워크플로우트리거 조건실행 내용
code_quality_checks.yml모든 PRpre-commit --all-files (isort, ruff, mypy, SPDX 헤더, torch 직접 사용 금지, clang-format)
test.ymltest job**.py, pyproject.toml, requirements 변경non-CUDA 유닛테스트, Python 3.10/3.11/3.12/3.13 × ubuntu
test.ymlraw-block-tests jobraw_block 관련 파일 변경 시만Rust 익스텐션 빌드 후 raw_block 특화 테스트 3개만 실행
macos_compat.ymlPR (관련 변경)macOS CPU-only smoke test (서버 기동 확인 수준)
codeql.ymlPR / 스케줄Python + Actions 정적 보안 분석 (C/CUDA는 GPU 러너 없어 비활성)

PR CI에서 --ignore로 제외되는 테스트

tests/disagg/ # NIXL 분산 prefill
tests/v1/multiprocess/ # 멀티프로세스 파이프라인
tests/v1/distributed/ # P2P / disagg
tests/v1/mp_observability/ # 멀티프로세스 관측성
tests/skipped/
tests/cli/commands/trace/
tests/v1/storage_backend/test_eic.py
tests/v1/storage_backend/test_p2p_backend_with_controller.py

raw-block-tests job에서는 test_raw_block_l2_adapter.py(멀티프로세스 디렉토리 안) 한 파일만 예외적으로 실행된다.


2. raw_block 모듈 테스트 커버리지

총 5개 파일, raw-block-tests CI job에서 3개가 실행되고 나머지 2개는 표준 test job에서 실행된다.

커버되는 것

  • 기본 CRUD: put_many / load_many_into / exists_many / delete_many (단일·다중, 누락 키 포함)
  • 중복 put: 원본 payload 보존 (덮어쓰기 방지)
  • Checkpoint: 저장·복구, 손상된 최신 카피 대체, 무효 항목 스킵, 레거시 dtype 복구
  • Lock refcount / pin·unpin: idempotency 및 동시 close 스레드 안전성
  • 배치 remove: force flag에 따른 pinned 키 보존/제거 동작
  • TP(Tensor Parallelism): 멀티 GPU per-tp device 경로
  • Device I/O: POSIX pread/pwrite, io_uring batched 읽기/쓰기, 용량 초과 에러
  • Key codec: ObjectKey ↔ 문자열 라운드트립, URL 인코딩 슬래시 포함 경로명

커버 안 되는 것

미커버 항목파일 위치비고
_checkpoint_loop() — 주기적 체크포인트 스레드core.pymeta_enable_periodic=False로 모든 테스트에서 비활성화
O_DIRECT 경로 전반core.py, Rust lib.rsLMCACHE_RUN_ODIRECT_SMOKE=1 설정 시만 실행(opt-in)
normalize_raw_block_io_engine() / validate_raw_block_io_options()raw_block/ 설정 모듈설정 검증 함수 자체가 테스트 없음
io_uring 미지원 환경 폴백Rust lib.rs"best-effort skip" 로직 존재하지만 강제 장애 시나리오 없음
동시 put/delete 경합 상태core.pyrace condition 시나리오 없음
_snapshot_state() lock hold 시간core.py 1102-1145인덱스 대용량(1만+ entry) 시 성능 미검증
_free_slots 멤버십 체크 O(n) 실측core.py코드상 확인은 됐으나 부하 테스트 없음

3. 멀티프로세스 / 분산 테스트 실행 방식

CI 계층 구조

PR CI (GitHub Actions, 공개)
└─ test.yml: multiprocess/distributed 전부 --ignore
└─ raw-block-tests: test_raw_block_l2_adapter.py 한 파일만

K3 파이프라인 (내부 CI, 비공개)
└─ 실제 멀티프로세스 + GPU 테스트
└─ 최근 커밋 흔적: pod spec 1-GPU/2-GPU 조정, 병렬화 등 활발
└─ PR CI 결과에 보이지 않음 → 외부 기여자 기준 블랙박스

disagg (tests/disagg/)
└─ NIXL 기반, 어느 공개 CI에도 포함 안 됨

테스트 설계 방식 (코드 구조)

  • multiprocess 테스트: subprocess 스폰 + ZMQ IPC 기반. conftest.pymemory_allocator (session-scoped, 5GB 공유 MixedMemoryAllocator)가 핵심 픽스처.
  • distributed 테스트: 단일 프로세스 in-memory 시뮬레이션. GPU 없이 돌 수 있는 것들. conftest.pynative_storage_ops 미설치 시 Python fallback Bitmap/TTLLock stub 제공.
  • disagg 테스트: NIXL 라이브러리 필수. 실제 원격 스토리지 채널 연결.

4. 새 PR 작업 시 — 실장 테스트가 필요한 경우

아래 변경 유형은 PR CI(GitHub Actions)를 통과해도 실제 동작을 보장하지 않는다. PR 올리기 전 로컬 또는 실장 환경에서 직접 확인해야 한다.

4-1. GPU / CUDA 경로를 건드린 경우

  • lmcache/v1/storage_backend/raw_block/ 내 CUDA-aware 코드
  • rust/raw_block/ Rust 익스텐션 (io_uring, O_DIRECT 등 커널 기능)
  • lmcache/v1/distributed/l2_adapters/raw_block_l2_adapter.py의 GPU 전송 경로

확인 방법: GPU 장비에서 pytest tests/v1/storage_backend/test_rust_raw_block_backend.py -xvs


4-2. 멀티프로세스 파이프라인을 건드린 경우

tests/v1/multiprocess/ 전체가 PR CI에서 skip된다. 아래 파일을 수정했다면:

  • lmcache/v1/multiprocess/ — MP 런타임, MessageQueue, blend server
  • lmcache/v1/storage_backend/plugins/rust_raw_block_backend.py — MP 경로에서 사용
  • lmcache/v1/distributed/l2_adapters/raw_block_l2_adapter.py

확인 방법:

# 로컬에서 멀티프로세스 테스트 실행 (non-GPU 가능한 것부터)
pytest -xvs tests/v1/multiprocess/ --ignore=tests/v1/multiprocess/test_gpu_context.py

4-3. Checkpoint / 주기적 체크포인트 스레드를 건드린 경우

core.py_checkpoint_loop() / meta_enable_periodic 관련 코드는 모든 테스트에서 비활성화 상태로 실행된다.

확인 방법: meta_enable_periodic=True로 명시적으로 설정한 통합 테스트 직접 작성 또는 수동 검증.


4-4. O_DIRECT / io_uring 경로를 건드린 경우

O_DIRECT 테스트는 opt-in이고, io_uring은 "best-effort" 조건부 실행이라 CI에서 실제로 커버되지 않을 수 있다.

확인 방법:

LMCACHE_RUN_ODIRECT_SMOKE=1 pytest -xvs tests/v1/storage_backend/test_raw_block_device.py

4-5. 분산 / NIXL / P2P 경로를 건드린 경우

tests/v1/distributed/, tests/disagg/ 모두 PR CI에서 제외. NIXL 관련 변경은 특히 실장 환경(다중 노드) 없이는 검증 불가.


4-6. 변경 매핑 요약표

수정 파일/디렉토리CI 커버 여부실장 필요
rust/raw_block/ — 기본 put/get/checkpoint✅ raw-block-testsGPU: io_uring / O_DIRECT 경로는 별도 확인
lmcache/v1/storage_backend/raw_block/core.py✅ test job주기적 체크포인트 경로 별도 확인
lmcache/v1/storage_backend/plugins/rust_raw_block_backend.py✅ test jobMP 경로 사용 시 multiprocess 테스트 확인
lmcache/v1/distributed/l2_adapters/raw_block_l2_adapter.py⚠️ raw-block-tests에서 L2 adapter 테스트 일부만multiprocess 경로 직접 확인
lmcache/v1/multiprocess/**❌ PR CI skip로컬에서 tests/v1/multiprocess/ 직접 실행
lmcache/v1/distributed/**❌ PR CI skip로컬에서 tests/v1/distributed/ 직접 실행
tests/disagg/**❌ PR CI skipNIXL 실장 환경 필요
CUDA / GPU 익스텐션❌ GPU 러너 없음GPU 장비 필수