CI 커버리지 & 실장 테스트 가이드
작성: 2026-06-04
목적: LMCache PR CI가 실제로 어디까지 검증하는지 정리하고, CI 사각지대에서 실장 테스트가 필수인 경우를 기록한다.
1. PR CI 구조 요약
모든 워크플로우는 .github/workflows/에 있으며, dorny/paths-filter로 변경 경로를 감지해서 관련 있을 때만 job을 실행한다.
PR마다 자동으로 도는 것 (draft 포함)
| 워크플로우 | 트리거 조건 | 실행 내용 |
|---|---|---|
code_quality_checks.yml | 모든 PR | pre-commit --all-files (isort, ruff, mypy, SPDX 헤더, torch 직접 사용 금지, clang-format) |
test.yml → test job | **.py, pyproject.toml, requirements 변경 | non-CUDA 유닛테스트, Python 3.10/3.11/3.12/3.13 × ubuntu |
test.yml → raw-block-tests job | raw_block 관련 파일 변경 시만 | Rust 익스텐션 빌드 후 raw_block 특화 테스트 3개만 실행 |
macos_compat.yml | PR (관련 변경) | macOS CPU-only smoke test (서버 기동 확인 수준) |
codeql.yml | PR / 스케줄 | 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:
forceflag에 따른 pinned 키 보존/제거 동작 - TP(Tensor Parallelism): 멀티 GPU per-tp device 경로
- Device I/O: POSIX
pread/pwrite, io_uring batched 읽기/쓰기, 용량 초과 에러 - Key codec:
ObjectKey↔ 문자열 라운드트립, URL 인코딩 슬래시 포함 경로명
커버 안 되는 것
| 미커버 항목 | 파일 위치 | 비고 |
|---|---|---|
_checkpoint_loop() — 주기적 체크포인트 스레드 | core.py | meta_enable_periodic=False로 모든 테스트에서 비활성화 |
| O_DIRECT 경로 전반 | core.py, Rust lib.rs | LMCACHE_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.py | race 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.py의memory_allocator(session-scoped, 5GB 공유MixedMemoryAllocator)가 핵심 픽스처. - distributed 테스트: 단일 프로세스 in-memory 시뮬레이션. GPU 없이 돌 수 있는 것들.
conftest.py에native_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 serverlmcache/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-tests | GPU: 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 job | MP 경로 사용 시 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 skip | NIXL 실장 환경 필요 |
| CUDA / GPU 익스텐션 | ❌ GPU 러너 없음 | GPU 장비 필수 |