실사용 영상
--------------
이전 글에서는 Pintos Test Explorer가 Make 타깃으로 테스트를 실행하고, 생성된 결과 파일을 VS Code 사이드바에 표시하는 과정을 살펴봤다.
이번에는 사이드바와 터미널이 함께 사용하는 내부 실행 구조를 정리해보려고 한다.
프로젝트는 같은 기능을 제공하는 두 개의 명령을 포함한다.
pt pintos-tests
예를 들면 다음과 같이 사용할 수 있다.
pt list threads pt run threads alarm-zero pt debug threads alarm-zero pt artifacts threads alarm-zero
두 명령은 모두 pintos-test-cli.py를 실행한다.
CLI가 필요했던 이유
처음에는 VS Code 사이드바만 있으면 된다고 생각했다.
하지만 일부 작업은 터미널에서 실행하는 편이 더 편했다.
와일드카드로 테스트 실행 숫자 범위로 여러 테스트 실행 결과 파일 경로 확인 여러 테스트 결과 초기화 스크립트에서 테스트 실행
예를 들어 다음과 같이 사용할 수 있다.
pt run threads 11-20 pt run threads alarm-* pt reset threads all
사이드바와 CLI가 테스트 탐색 코드를 따로 구현하면 서로 다른 테스트 목록을 보여줄 가능성이 있었다.
그래서 사이드바에서도 번들로 포함된 Python 도우미를 사용하도록 했다.
VS Code 사이드바 → pintos-test-cli.py list threads --json → JSON 테스트 목록 → PintosTreeProvider → 사이드바 노드 생성
터미널에서는 같은 도우미를 직접 실행한다.
pt list threads → pintos-test-cli.py → 같은 테스트 탐색 로직
실행할 프로젝트와 Make 타깃, 결과 파일을 결정하는 규칙도 두 환경에서 동일하게 사용한다.
Makefile에서 테스트 찾기
Pintos 테스트 목록은 하나의 JSON 파일에 저장되어 있지 않다.
테스트는 Make.tests와 Make 변수를 이용해 등록한다.
단순한 등록은 다음과 비슷하다.
TESTS += tests/threads/alarm-zero TESTS += tests/threads/alarm-single
Make 표현식을 사용하는 경우도 있다.
tests/threads_TESTS = alarm-zero alarm-single TESTS += $(addprefix tests/threads/, $(tests/threads_TESTS))
초기 버전에서는 Make를 실행해 각 프로젝트의 테스트 목록을 계산했다.
정확한 방법이지만 프로젝트마다 Make를 반복해서 실행해야 해서 사이드바의 첫 로딩이 느렸다.
그래서 Make.tests를 직접 읽는 파서를 추가했다.
파서는 다음과 같은 할당 방식을 처리한다.
= := ?= +=
Pintos에서 자주 사용하는 Make 표현식도 일부 해석한다.
변수 참조 $(addprefix ...) $(patsubst ...)
직접 파싱하면서 탐색 속도는 빨라졌지만 새로운 문제가 생겼다.
Make.tests에 등록된 모든 테스트와 현재 프로젝트의 빌드 Makefile이 최종적으로 선택한 TESTS 목록이 항상 같지는 않았다.
그래서 현재는 두 정보를 함께 사용한다.
빌드 Makefile의 최종 TESTS → 프로젝트의 기본 테스트 목록 프로젝트 내부 Make.tests 등록 → 중첩되거나 선택적인 추가 테스트
프로젝트 전체 실행은 현재 빌드가 선택한 테스트를 기준으로 한다. 추가 테스트는 사이드바에 표시하되 사용자가 개별적으로 실행할 수 있도록 했다.
테스트를 올바른 프로젝트에 배치하기
일부 테스트 정의는 여러 빌드 환경에서 함께 참조될 수 있다.
필터링하지 않으면 alarm-* 같은 Threads 테스트가 User Programs 아래에 나타나는 문제가 발생할 수 있다.
각 프로젝트가 소유하는 테스트 경로를 명확하게 구분했다.
Threads → tests/threads/ User Programs → tests/userprog/ Virtual Memory → tests/vm/ File System → tests/filesys/
탐색 도우미는 테스트를 찾은 뒤 프로젝트의 경로와 일치하는 항목만 남긴다.
따라서 Makefile이 공통 변수를 포함하더라도 사이드바의 프로젝트 구조는 유지된다.
테스트 소스 파일 찾기
확장 프로그램은 각 테스트 행에 Open Test Source 기능을 제공한다.
가장 단순한 방식은 테스트 이름 뒤에 .c를 붙이는 것이다.
tests/threads/alarm-zero → tests/threads/alarm-zero.c
하지만 항상 정확하지는 않다.
Makefile의 _SRC 변수가 다른 소스 파일을 지정할 수 있고, Threads 테스트는 테스트 이름과 실제 C 함수 이름이 다르게 등록될 수도 있다.
그래서 도우미는 여러 정보를 순서대로 확인한다.
테스트의 _SRC 등록 확인 → 같은 이름의 .c 파일 확인 → Threads 테스트 등록 테이블 확인 → 등록된 함수가 정의된 소스 파일 탐색 → 가장 가능성이 높은 파일 선택
이를 통해 테스트 이름과 파일명이 정확히 같지 않아도 실제 구현 파일을 열 수 있다.
VS Code 터미널에서 CLI 사용하기
확장 프로그램이 활성화되면 번들로 포함된 CLI 파일을 VS Code 확장 프로그램 저장소로 복사한다.
그리고 새로 열리는 통합 터미널의 환경 변수를 설정한다.
CLI 디렉터리를 PATH에 추가 PINTOS_ROOT 설정 PINTOS_WORKSPACE_ROOT 설정
따라서 새 터미널에서는 바로 다음 명령을 사용할 수 있다.
pt --help
Pintos 루트는 확장 프로그램이 탐색한 경로로 고정한다.
랩 저장소 안에서 디렉터리를 이동하더라도 다른 Pintos 트리의 결과 파일을 잘못 읽는 문제를 줄이기 위한 것이다.
VS Code 외부 터미널에서도 사용하려면 다음 경로에 작은 실행 래퍼를 설치할 수 있다.
~/.local/bin
Pintos 테스트 디버깅
테스트 실행과 테스트 디버깅은 서로 다른 과정이다.
일반 실행은 Pintos를 시작하고 검사 결과가 생성되기를 기다리면 된다. 디버깅에서는 Pintos를 GDB 서버 모드로 실행하고, VS Code가 연결될 때까지 프로세스를 유지해야 한다.
GDB 실행 준비는 pintos-gdb-server.sh가 담당한다.
처음에는 다음 명령만 실행하면 될 것 같았다.
gdb kernel.o
하지만 kernel.o만으로는 어떤 테스트를 실행할지 알 수 없다.
테스트 프로그램을 Pintos 파일 시스템에 복사하는 옵션과 QEMU 실행 인자도 필요하다.
그래서 먼저 Make에 실제 테스트 실행 명령을 출력하도록 요청한다.
make -n tests/threads/alarm-zero.output
-n 옵션을 사용하면 명령을 실행하지 않고 실행 예정인 명령만 출력한다.
도우미는 출력에서 실제 pintos 명령을 찾고, 디버깅용으로 변환한다.
일반 테스트 실행 명령 확인 → 선택한 테스트와 복사할 파일 정보 유지 → Pintos --gdb 옵션 추가 → QEMU GDB 서버 실행 → 1234번 포트가 열릴 때까지 대기 → VS Code에 준비 완료 알림
그다음 VS Code는 cppdbg 설정으로 GDB 서버에 연결한다.
프로그램: project/build/kernel.o 디버거: gdb 서버: 127.0.0.1:1234
전체 흐름은 다음과 같다.
Debug 버튼 클릭 → 프로젝트 빌드 트리 준비 → 실제 Pintos 테스트 명령 추출 → Pintos와 QEMU를 GDB 모드로 실행 → GDB 서버 준비 대기 → VS Code C/C++ 디버거 연결 → 커널 디버깅
VS Code 디버그 세션이 종료되면 확장 프로그램이 GDB 서버를 중단하고 저장된 프로세스 상태를 정리한다.
VM 빌드에서 User Programs 테스트 실행하기
Virtual Memory를 구현하는 중에도 User Programs 테스트를 실행해야 할 때가 있다.
테스트는 User Programs 목록에 남겨두되 VM 커널을 기준으로 실행해야 한다.
그래서 User Programs for VM 체크박스를 추가했다.
체크 해제 User Programs 테스트 → userprog/build 사용 체크 User Programs 테스트 → vm/build 사용
여기서는 테스트가 속한 프로젝트와 실제 실행에 사용할 프로젝트를 분리한다.
소스 프로젝트: User Programs 빌드 프로젝트: Virtual Memory
테스트는 User Programs 아래에 계속 표시되지만 실행, 디버깅, 결과 파일 확인은 vm/build를 기준으로 동작한다.
사용자 테스트 관리
Pintos 사용자 테스트는 C 파일 하나만 만든다고 등록되지 않는다.
프로젝트에 따라 다음 작업이 필요하다.
C 소스 파일 생성 검사 파일 생성 Make.tests 등록 Threads 테스트 함수 등록 빌드 결과 디렉터리 생성
테스트의 이름을 바꾸거나 삭제할 때도 같은 파일과 등록 정보를 함께 수정해야 한다.
소스 파일만 삭제하고 Make.tests 등록이 남아 있으면 Make가 존재하지 않는 테스트를 계속 빌드하려고 하기 때문에 다른 테스트까지 실패할 수 있다.
그래서 사용자 테스트 명령은 관련 파일을 하나의 단위로 관리한다.
pt custom create threads custom/alarm/new-test pt custom rename threads custom/alarm custom/alarm-clock pt custom delete threads custom/alarm-clock
VS Code의 생성, 이름 변경, 삭제 기능도 같은 도우미를 호출한다.
VS Code 명령 → pintos-test-cli.py custom ... → 소스 파일 수정 → Make.tests 수정 → 테스트 등록 수정 → 결과 파일 이동 또는 삭제 → 사이드바 갱신
프로젝트가 발전한 과정
현재 구조가 처음부터 한 번에 만들어진 것은 아니다.
0.1.0 - Pintos Activity Bar - Run과 Debug 버튼 - 체크박스 기반 일괄 실행 - 결과 파일 링크 0.1.1 - 테스트 탐색 및 GDB 도우미 번들 - 래퍼 저장소 구조 지원 0.1.2 - Make.tests 기반 빠른 테스트 탐색 - GDB 시작 오류 개선 0.1.8~0.2.0 - pt와 pintos-tests CLI 통합 - 외부 셸 실행 래퍼 - Pintos 루트 탐색 범위 확장 0.2.1~0.2.4 - 공통 CLI를 통한 사용자 테스트 관리 - 테스트 소스 탐색 개선 - 불완전한 빌드 디렉터리 복구 - 비동기 탐색 중 체크박스 상태 안정화 0.2.9 - 빌드의 최종 TESTS 목록과 탐색 결과 일치 - 중첩 Make.tests 추가 탐색 - 루트 및 결과 파일 선택 규칙 통합 0.3.0 - vm/build를 이용한 User Programs 테스트 실행
전체 변경 과정은 프로젝트의 CHANGELOG에서 확인할 수 있다.
결론
최종 구조는 다음과 같이 정리할 수 있다.
VS Code 사이드바 │ ├─ Python 도우미 │ ├─ Pintos 루트 탐색 │ ├─ 테스트 탐색 │ ├─ 소스 파일 탐색 │ ├─ CLI 명령 │ └─ 사용자 테스트 관리 │ ├─ 기존 Pintos Make 타깃 │ └─ output / result / errors │ └─ GDB 서버 도우미 └─ VS Code C/C++ 디버거
이 확장 프로그램은 Pintos의 빌드, 테스트, 디버깅 도구를 새로 만드는 것이 아니다.
기존 도구들을 연결해 같은 테스트를 사이드바와 터미널에서 탐색하고, 실행하고, 결과를 확인하고, 디버깅할 수 있도록 만든 것이다.
반복해서 Make 명령을 입력하지 않기 위해 시작했지만, 만들고 나니 Makefile 파싱, 프로세스 관리, 결과 파일 동기화, 원격 커널 디버깅까지 함께 다루게 된 프로젝트였다.