Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

[インデックス 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行の変更を加えました:

  1. 定数宣言の型修正

    // 変更前
    ERROR_OLD_WIN_VERSION = 1150
    
    // 変更後
    ERROR_OLD_WIN_VERSION syscall.Errno = 1150
    
  2. エラーメッセージ出力の修正

    // 変更前
    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型に変更することでした。これにより以下の利点が得られます:

  1. 型安全性の向上:コンパイル時に型の不一致を検出
  2. 標準ライブラリとの互換性errors.Isによる一貫したエラー比較
  3. プラットフォーム間の統一性: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移植では以下の課題がありました:

  1. エラーコードの不統一:各プラットフォームで独自のエラー定数を定義
  2. 型システムとの非互換性:整数定数とErrno型の混在
  3. 標準ライブラリとの連携不備:エラー比較の一貫性欠如

コアとなるコードの変更箇所

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関数を使用してシステムバージョンの検証を行います:

  1. OSVersionInfoEx構造体の準備:現在のWindowsバージョン情報を格納
  2. VerifyVersionInfoW API呼び出し:指定された条件でバージョン比較を実行
  3. 戻り値の検証:成功時は非ゼロ、失敗時はゼロを返す
  4. エラーハンドリング:特定のエラー(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 { ... }     // タイムアウトエラーの判定

この型設計により、プラットフォーム固有のエラーコードを統一的に扱えるようになっています。

テストの品質向上

修正後のコードは以下の観点で品質が向上しました:

  1. 型安全性:コンパイル時の型チェックによる不具合の早期発見
  2. 可読性:エラーメッセージの簡潔性と一貫性
  3. 保守性:標準ライブラリとの統合による将来的な拡張性

関連リンク

参考にした情報源リンク