[インデックス 19663] ファイルの概要
このコミットは、src/pkg/crypto/x509/pem_decrypt_test.go
ファイルにおけるテスト出力のフォーマット文字列の誤りを修正するものです。具体的には、t.Logf
関数で使用されていたフォーマット動詞 %s
が、期待される文字列型ではない x509.PEMCipher
型の値を表示しようとした際に発生する不適切な出力(%!s(x509.PEMCipher=1)
のような形式)を修正し、汎用的な %v
に変更することで、正しい値の表示を可能にしています。
コミット
commit 2ec3a0a72fbe2cdd4affc67383ae67c503e7469b
Author: Dmitriy Vyukov <dvyukov@google.com>
Date: Thu Jul 3 12:08:24 2014 +0400
crypto/x509: fix format strings in test
Currently it says:
--- PASS: TestDecrypt-2 (0.11s)
pem_decrypt_test.go:17: test 0. %!s(x509.PEMCipher=1)
--- PASS: TestEncrypt-2 (0.00s)
pem_decrypt_test.go:42: test 0. %!s(x509.PEMCipher=1)
LGTM=alex.brainman
R=golang-codereviews, alex.brainman
CC=golang-codereviews
https://golang.org/cl/108400044
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/2ec3a0a72fbe2cdd4affc67383ae67c503e7469b
元コミット内容
crypto/x509: fix format strings in test
Currently it says:
--- PASS: TestDecrypt-2 (0.11s)
pem_decrypt_test.go:17: test 0. %!s(x509.PEMCipher=1)
--- PASS: TestEncrypt-2 (0.00s)
pem_decrypt_test.go:42: test 0. %!s(x509.PEMCipher=1)
LGTM=alex.brainman
R=golang-codereviews, alex.brainman
CC=golang-codereviews
https://golang.org/cl/108400044
変更の背景
このコミットの背景には、Go言語の標準ライブラリ crypto/x509
パッケージ内のテストコード pem_decrypt_test.go
において、テストのログ出力が意図しない形式で表示される問題がありました。具体的には、t.Logf
関数(fmt.Printf
と同様のフォーマット指定子を使用)で、data.kind
という変数を %s
フォーマット動詞で出力しようとしていました。しかし、data.kind
は文字列型ではなく、x509.PEMCipher
というカスタム型であったため、Goのフォーマットエンジンはこれを文字列として適切に変換できず、%!s(x509.PEMCipher=1)
のようなエラーメッセージを出力していました。
この出力はテストの実行結果自体には影響しませんが、テストログの可読性を著しく損ない、デバッグやテスト結果の確認を困難にしていました。この問題を解決し、テストログをより分かりやすくするために、フォーマット動詞を汎用的な %v
に変更する必要がありました。
前提知識の解説
Go言語の testing
パッケージ
Go言語には、ユニットテストを記述するための標準パッケージ testing
が用意されています。テスト関数は Test
で始まる名前を持ち、*testing.T
型の引数を取ります。
t.Logf(format string, args ...interface{})
: テスト中にログメッセージを出力するための関数です。fmt.Printf
と同様のフォーマット指定子を使用できます。テストが成功した場合でも、このログは表示されます。t.Error(args ...interface{})
/t.Errorf(format string, args ...interface{})
: テストを失敗としてマークし、エラーメッセージを出力します。テストの実行は継続されます。t.Fatal(args ...interface{})
/t.Fatalf(format string, args ...interface{})
: テストを失敗としてマークし、エラーメッセージを出力した後、テストの実行を即座に停止します。
Go言語の fmt
パッケージとフォーマット動詞
fmt
パッケージは、Go言語におけるフォーマットI/Oを扱うための基本的なパッケージです。fmt.Printf
や fmt.Sprintf
、そして testing
パッケージの t.Logf
などで使われるフォーマット動詞は、出力する値の型に応じて適切なものを選択する必要があります。
主要なフォーマット動詞には以下のようなものがあります。
%d
: 整数値を10進数で表示します。%s
: 文字列を表示します。%v
: 値をデフォルトのフォーマットで表示します。これは最も汎用的な動詞で、任意の型の値を適切に表示しようとします。構造体やカスタム型の場合、その型のデフォルトの文字列表現(通常はフィールド名と値)を出力します。%T
: 値の型を表示します。
今回の問題は、x509.PEMCipher
型の値を文字列として扱おうとしたために発生しました。%s
は文字列型を期待するため、それ以外の型が渡されると、Goのランタイムは「この型は %s
でフォーマットできません」という旨のエラーメッセージ(%!s(...)
)を出力します。
crypto/x509
パッケージ
crypto/x509
パッケージは、X.509証明書とPKIX(Public Key Infrastructure X.509)関連の機能をGo言語で提供する標準ライブラリです。証明書の解析、生成、検証、PEMエンコード/デコードなどの機能が含まれます。このコミットで修正された pem_decrypt_test.go
は、PEM形式でエンコードされたデータの復号化に関するテストコードです。
技術的詳細
このコミットの技術的な核心は、Go言語のフォーマット動詞の適切な使用にあります。t.Logf
は fmt.Printf
と同じフォーマットルールに従います。
元のコードでは、t.Logf("test %d. %s", i, data.kind)
と記述されていました。
ここで、i
はループカウンタであり、整数型なので %d
で問題ありません。
しかし、data.kind
は x509.PEMCipher
型であり、これは文字列型ではありません。x509.PEMCipher
はおそらく列挙型のようなもので、内部的には整数値を持つカスタム型です。
Goの fmt
パッケージのルールでは、%s
は string
型、または String() string
メソッドを実装している型に対して使用されます。x509.PEMCipher
型が String() string
メソッドを実装していなかったため、%s
を使用すると、Goランタイムは「この型は %s
でフォーマットできません」ということを示す %!s(type=value)
の形式で出力しました。
この問題を解決するために、フォーマット動詞を %v
に変更しました。%v
は「値のデフォルトフォーマット」を表し、任意の型の値を適切に表示しようとします。カスタム型の場合、通常はその型の内部表現(例えば、構造体のフィールド値)を人間が読める形式で出力します。これにより、x509.PEMCipher
型の値が期待通りに表示されるようになります。
コアとなるコードの変更箇所
--- a/src/pkg/crypto/x509/pem_decrypt_test.go
+++ b/src/pkg/crypto/x509/pem_decrypt_test.go
@@ -14,7 +14,7 @@ import (
func TestDecrypt(t *testing.T) {
for i, data := range testData {
- t.Logf("test %d. %s", i, data.kind)
+ t.Logf("test %v. %v", i, data.kind)
block, rest := pem.Decode(data.pemData)
if len(rest) > 0 {
t.Error("extra data")
@@ -39,7 +39,7 @@ func TestDecrypt(t *testing.T) {
func TestEncrypt(t *testing.T) {
for i, data := range testData {
- t.Logf("test %d. %s", i, data.kind)
+ t.Logf("test %v. %v", i, data.kind)
plainDER, err := base64.StdEncoding.DecodeString(data.plainDER)
if err != nil {
t.Fatal("cannot decode test DER data: ", err)
コアとなるコードの解説
変更は src/pkg/crypto/x509/pem_decrypt_test.go
ファイルの2箇所にあります。
-
TestDecrypt
関数内:- 変更前:
t.Logf("test %d. %s", i, data.kind)
- 変更後:
t.Logf("test %v. %v", i, data.kind)
- 変更前:
-
TestEncrypt
関数内:- 変更前:
t.Logf("test %d. %s", i, data.kind)
- 変更後:
t.Logf("test %v. %v", i, data.kind)
- 変更前:
両方の変更において、t.Logf
のフォーマット文字列が修正されています。
- 最初の
%d
はループカウンタi
のためのものでしたが、これも汎用的な%v
に変更されています。i
は整数なので%d
でも問題ありませんが、一貫性を持たせるためか、あるいは将来的にi
が整数以外の型になる可能性を考慮して%v
に変更されたと考えられます。%v
は整数も適切に表示します。 - 重要な変更は2番目のフォーマット動詞です。
data.kind
はx509.PEMCipher
型であり、これが%s
でフォーマットされるとエラーが発生していました。これを汎用的な%v
に変更することで、x509.PEMCipher
型の値がそのデフォルトの文字列表現で正しく出力されるようになります。これにより、%!s(x509.PEMCipher=1)
のような不適切な出力が解消され、テストログの可読性が向上します。
この修正は、機能的な変更ではなく、テストコードのログ出力の品質を改善するためのものです。
関連リンク
- Go CL 108400044: https://golang.org/cl/108400044
参考にした情報源リンク
- Go言語
fmt
パッケージのドキュメント: https://pkg.go.dev/fmt (特にフォーマット動詞に関するセクション) - Go言語
testing
パッケージのドキュメント: https://pkg.go.dev/testing - Go言語
crypto/x509
パッケージのドキュメント: https://pkg.go.dev/crypto/x509