[インデックス 10377] ファイルの概要
Windows向けランタイムのsyscallテストにおけるエラーハンドリング修正に関するコミット。テスト内のエラー型定義を既存のsyscall.Errno
型に統一し、Goの標準ライブラリとの互換性を向上させました。
コミット
commit 946647fb452dc32b08d9b028298ab5ad24f0ecfe
Author: Alex Brainman <alex.brainman@gmail.com>
Date: Mon Nov 14 20:54:47 2011 +1100
runtime: fix syscall test to satisfy new error
R=rsc
CC=golang-dev
https://golang.org/cl/5369103
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/946647fb452dc32b08d9b028298ab5ad24f0ecfe
元コミット内容
このコミットは、Windowsランタイムのsyscallテストファイル(src/pkg/runtime/syscall_windows_test.go
)に2行の変更を加えました:
-
定数宣言の型修正:
// 変更前 ERROR_OLD_WIN_VERSION = 1150 // 変更後 ERROR_OLD_WIN_VERSION syscall.Errno = 1150
-
エラーメッセージ出力の修正:
// 変更前 t.Errorf("VerifyVersionInfo failed: (%d) %s", e2, syscall.Errstr(int(e2))) // 変更後 t.Errorf("VerifyVersionInfo failed: %s", e2)
これらの変更により、テストコードがGoの標準的なエラーハンドリングパターンに準拠するようになりました。
変更の背景
この修正は、2011年当時のGoにおけるWindows環境でのエラーハンドリング標準化の一環として行われました。Alex Brainmanは、Go言語のWindows移植における中心的な貢献者であり、このコミットは彼の継続的なWindows対応作業の一部でした。
当時のGoは、異なるプラットフォーム間でのエラーハンドリングの一貫性を確保する必要がありました。特にWindowsプラットフォームでは、Unix系システムとは異なるエラーコード体系を持つため、標準ライブラリ全体での統一されたエラー型が重要でした。
前提知識の解説
syscall.Errnoとは
syscall.Errno
は、Goの標準ライブラリで定義されているシステムコールのエラー番号を表す型です。Windows環境では以下のように定義されています:
type Errno uintptr
この型は以下の特徴を持ちます:
- OSのエラー番号を直接保持
error
インターフェースを実装errors.Is
による型安全なエラー比較をサポート- プラットフォーム固有のエラーコードを統一的に扱う
WindowsのERROR_OLD_WIN_VERSION
ERROR_OLD_WIN_VERSION
(値:1150)は、Windows APIで定義されているエラーコードで、実行中のWindowsバージョンがアプリケーションが要求するバージョンより古い場合に返されます。このエラーは、VerifyVersionInfoW
API関数によってよく使用されます。
Test64BitReturnStdCallテスト
このテストは、64ビットWindowsプラットフォームでの標準呼び出し規約(stdcall)の動作を検証するものです。Windows APIのVerifyVersionInfoW
関数を使用して、システムバージョンの検証機能をテストしています。
技術的詳細
エラー型の標準化
この修正の核心は、ローカルで定義された整数定数をsyscall.Errno
型に変更することでした。これにより以下の利点が得られます:
- 型安全性の向上:コンパイル時に型の不一致を検出
- 標準ライブラリとの互換性:
errors.Is
による一貫したエラー比較 - プラットフォーム間の統一性:Unix系とWindows系の統一されたエラーハンドリング
エラーメッセージの簡略化
エラーメッセージの出力方法も改善されました:
// 変更前:手動でのエラー番号表示と文字列変換
t.Errorf("VerifyVersionInfo failed: (%d) %s", e2, syscall.Errstr(int(e2)))
// 変更後:Errno型のString()メソッドを活用
t.Errorf("VerifyVersionInfo failed: %s", e2)
この変更により、syscall.Errno
型が持つ組み込みの文字列変換機能が活用され、より簡潔で保守しやすいコードになりました。
Windows版Go移植での課題
2011年当時、Go言語のWindows移植では以下の課題がありました:
- エラーコードの不統一:各プラットフォームで独自のエラー定数を定義
- 型システムとの非互換性:整数定数とErrno型の混在
- 標準ライブラリとの連携不備:エラー比較の一貫性欠如
コアとなるコードの変更箇所
1. 定数宣言部分(22-23行目)
// src/pkg/runtime/syscall_windows_test.go:22-23
VER_LESS_EQUAL = 5
- ERROR_OLD_WIN_VERSION = 1150
+ ERROR_OLD_WIN_VERSION syscall.Errno = 1150
この変更により、定数が明示的にsyscall.Errno
型として宣言されるようになりました。
2. エラーハンドリング部分(30-32行目)
// src/pkg/runtime/syscall_windows_test.go:30-32
if r == 0 && e2 != ERROR_OLD_WIN_VERSION {
- t.Errorf("VerifyVersionInfo failed: (%d) %s", e2, syscall.Errstr(int(e2)))
+ t.Errorf("VerifyVersionInfo failed: %s", e2)
}
この変更により、エラーメッセージの出力がより簡潔になり、syscall.Errno
型の持つ標準的な文字列表現機能を活用するようになりました。
コアとなるコードの解説
VerifyVersionInfoテストの動作原理
このテストは、Windows APIのVerifyVersionInfoW
関数を使用してシステムバージョンの検証を行います:
- OSVersionInfoEx構造体の準備:現在のWindowsバージョン情報を格納
- VerifyVersionInfoW API呼び出し:指定された条件でバージョン比較を実行
- 戻り値の検証:成功時は非ゼロ、失敗時はゼロを返す
- エラーハンドリング:特定のエラー(ERROR_OLD_WIN_VERSION)以外はテスト失敗
型システムとの統合
syscall.Errno
型は、Goの型システムと以下のように統合されています:
type Errno uintptr
func (e Errno) Error() string { ... } // error インターフェース実装
func (e Errno) Is(target error) bool { ... } // errors.Is 対応
func (e Errno) Temporary() bool { ... } // 一時的エラーの判定
func (e Errno) Timeout() bool { ... } // タイムアウトエラーの判定
この型設計により、プラットフォーム固有のエラーコードを統一的に扱えるようになっています。
テストの品質向上
修正後のコードは以下の観点で品質が向上しました:
- 型安全性:コンパイル時の型チェックによる不具合の早期発見
- 可読性:エラーメッセージの簡潔性と一貫性
- 保守性:標準ライブラリとの統合による将来的な拡張性