[インデックス 17363] ファイルの概要
このコミットは、Go言語の標準ライブラリであるnet
パッケージ内のipraw_test.go
ファイルに対する変更です。ipraw_test.go
は、IPアドレスの解決や生IPソケットに関連する機能のテストを目的としたファイルです。具体的には、net.ResolveIPAddr
関数の挙動を検証するためのテストケースが含まれています。
コミット
このコミットは、net.ResolveIPAddr
関数がプロトコル番号を内部情報ベースを使用してルックアップする際のテストを追加します。特に、プロトコル名のケースセンシティブな処理に関するテストケースが追加されています。これにより、ResolveIPAddr
がプロトコル名を適切に解釈できることを保証します。
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/d3043b7b4ac636fd1c2e43ff5e77e84a08b9a49f
元コミット内容
commit d3043b7b4ac636fd1c2e43ff5e77e84a08b9a49f
Author: Mikio Hara <mikioh.mikioh@gmail.com>
Date: Thu Aug 22 12:13:54 2013 +0900
net: add test for protocol numbers lookup using internal information base
Update #5344
R=alex.brainman
CC=golang-dev
https://golang.org/cl/12966046
変更の背景
この変更の背景には、net.ResolveIPAddr
関数がプロトコル名を解決する際の堅牢性を高めるという目的があります。ResolveIPAddr
は、ネットワークアドレスとプロトコル名を組み合わせてIPアドレスを解決する際に使用されます。例えば、"ip6:ipv6-icmp"
のように、ネットワークタイプとプロトコル名をコロンで区切って指定することができます。
既存のテストでは、"ip6:ipv6-icmp"
のような小文字のプロトコル名に対するテストは存在しましたが、"ip6:IPv6-ICMP"
のように大文字を含むプロトコル名が指定された場合に、ResolveIPAddr
が正しくプロトコル番号をルックアップできるかどうかの保証がありませんでした。
このコミットは、この潜在的な問題を解決するために、大文字を含むプロトコル名("ip6:IPv6-ICMP"
)に対するテストケースを追加し、ResolveIPAddr
が内部のプロトコル情報ベースを使用して、プロトコル名をケースインセンシティブに、または少なくとも一般的な大文字・小文字の組み合わせで正しく解決できることを確認することを目的としています。
コミットメッセージにあるUpdate #5344
は、Goプロジェクト内の特定の課題(issue)を参照している可能性がありますが、公開されているGoのGitHubリポジトリのissueトラッカーでは直接的な関連が見つかりませんでした。これは、内部的なトラッキング番号であるか、あるいは非常に古いissueであるため、現在の公開データベースからは参照できない可能性があります。しかし、変更内容から推測すると、プロトコル名の解決における堅牢性向上に関する課題であったと考えられます。
前提知識の解説
Go言語のnet
パッケージ
net
パッケージは、Go言語におけるネットワークI/Oの主要なインターフェースを提供します。TCP/IP、UDP、Unixドメインソケットなど、様々なネットワークプロトコルを扱うための機能が含まれています。ネットワークアドレスの解決、接続の確立、データの送受信など、低レベルから高レベルまでのネットワーク操作をサポートします。
IPAddr
構造体
net.IPAddr
は、IPアドレスを表す構造体です。以下のフィールドを持ちます。
IP net.IP
: IPアドレス自体(IPv4またはIPv6)。Zone string
: IPv6アドレスのスコープゾーン識別子。リンクローカルアドレスなどで使用されます。
ParseIP
関数
net.ParseIP
関数は、文字列形式のIPアドレス(例: "192.168.1.1"
, "::1"
)をnet.IP
型に変換します。無効なIPアドレス文字列が与えられた場合はnil
を返します。
ResolveIPAddr
関数
net.ResolveIPAddr
関数は、ネットワークタイプと文字列形式のアドレス(ホスト名やIPアドレス)を指定して、対応する*net.IPAddr
を解決します。
関数のシグネチャは以下の通りです。
func ResolveIPAddr(net, addr string) (*IPAddr, error)
net
: ネットワークタイプを指定します。例えば、"ip"
(任意のIPプロトコル)、"ip4"
(IPv4)、"ip6"
(IPv6)などがあります。また、"ip6:ipv6-icmp"
のように、コロンで区切って特定のプロトコル名を指定することもできます。addr
: 解決するアドレス文字列です。IPアドレスの文字列形式やホスト名が含まれます。
この関数は、指定されたネットワークタイプとアドレスに基づいて、適切なIPアドレスとゾーン情報を解決し、*net.IPAddr
構造体として返します。エラーが発生した場合はerror
を返します。
プロトコル番号とプロトコル名
TCP/IPネットワークでは、各プロトコルは一意のプロトコル番号によって識別されます。例えば、ICMP (Internet Control Message Protocol) はプロトコル番号1、TCP (Transmission Control Protocol) はプロトコル番号6、UDP (User Datagram Protocol) はプロトコル番号17などです。
これらのプロトコル番号には、人間が読みやすいように対応するプロトコル名が割り当てられています。例えば、ICMPは"icmp"
、IPv6-ICMPは"ipv6-icmp"
といった名前です。オペレーティングシステムは通常、これらのプロトコル名と番号のマッピングを内部的に保持しています(例: Unix系システムでは/etc/protocols
ファイル)。
net.ResolveIPAddr
のような関数がプロトコル名を引数として受け取る場合、内部的にはこのプロトコル名から対応するプロトコル番号をルックアップし、それを使用してネットワーク操作を行います。このルックアップ処理において、プロトコル名の大文字・小文字を区別するかどうかが問題となることがあります。
技術的詳細
このコミットの技術的な詳細は、net.ResolveIPAddr
関数がプロトコル名を解決する際のケースセンシティブな挙動をテストすることにあります。
resolveIPAddrTests
というテストデータスライスに、新しいテストケースが追加されています。
{"ip6:IPv6-ICMP", "::1", &IPAddr{IP: ParseIP("::1")}, nil},
このテストケースは、以下の要素で構成されています。
net
:"ip6:IPv6-ICMP"
ip6
: ネットワークタイプとしてIPv6を指定します。IPv6-ICMP
: プロトコル名としてIPv6-ICMP
を指定します。注目すべきは、既存のテストケースがipv6-icmp
(小文字)を使用しているのに対し、この新しいテストケースではIPv6-ICMP
(大文字を含む)を使用している点です。
litAddr
:"::1"
- ループバックIPv6アドレスです。
addr
:&IPAddr{IP: ParseIP("::1")}
- 期待される解決結果の
IPAddr
構造体です。::1
が正しくパースされることを期待します。
- 期待される解決結果の
err
:nil
- エラーが発生しないことを期待します。
このテストケースが追加されることで、ResolveIPAddr
関数が"IPv6-ICMP"
というプロトコル名を正しくIPv6-ICMP
プロトコル番号にマッピングできるかどうかが検証されます。もしResolveIPAddr
の内部実装がプロトコル名のルックアップにおいて大文字・小文字を厳密に区別する場合、このテストは失敗するでしょう。テストが成功するということは、ResolveIPAddr
がプロトコル名をケースインセンシティブに、または少なくとも一般的な大文字・小文字の組み合わせを許容して解決できることを意味します。
また、テスト失敗時のエラーメッセージの出力方法も変更されています。
- condFatalf(t, "ResolveIPAddr(%v, %v) failed: %v", tt.net, tt.litAddr, err)
+ t.Fatalf("ResolveIPAddr(%v, %v) failed: %v", tt.net, tt.litAddr, err)
condFatalf
からt.Fatalf
への変更は、テストフレームワークの慣用的な使用法への調整と考えられます。t.Fatalf
は、テストを失敗としてマークし、指定されたメッセージを出力してテストの実行を停止します。condFatalf
は、おそらく特定の条件が満たされた場合にのみt.Fatalf
を呼び出すヘルパー関数であったと推測されますが、この変更により、エラー発生時に直接t.Fatalf
が呼び出されるようになり、より直接的なエラー報告が行われるようになります。これは機能的な変更というよりは、テストコードの簡素化または標準化の一環である可能性が高いです。
コアとなるコードの変更箇所
diff --git a/src/pkg/net/ipraw_test.go b/src/pkg/net/ipraw_test.go
index 4f7d85aac7..fce0830a36 100644
--- a/src/pkg/net/ipraw_test.go
+++ b/src/pkg/net/ipraw_test.go
@@ -29,6 +29,7 @@ var resolveIPAddrTests = []resolveIPAddrTest{
{"ip", "::1", &IPAddr{IP: ParseIP("::1")}, nil},
{"ip6", "::1", &IPAddr{IP: ParseIP("::1")}, nil},
{"ip6:ipv6-icmp", "::1", &IPAddr{IP: ParseIP("::1")}, nil},
+ {"ip6:IPv6-ICMP", "::1", &IPAddr{IP: ParseIP("::1")}, nil},
{"ip", "::1%en0", &IPAddr{IP: ParseIP("::1"), Zone: "en0"}, nil},
{"ip6", "::1%911", &IPAddr{IP: ParseIP("::1"), Zone: "911"}, nil},
@@ -55,7 +56,7 @@ func TestResolveIPAddr(t *testing.T) {
for _, tt := range resolveIPAddrTests {
addr, err := ResolveIPAddr(tt.net, tt.litAddr)
if err != tt.err {
- condFatalf(t, "ResolveIPAddr(%v, %v) failed: %v", tt.net, tt.litAddr, err)
+ t.Fatalf("ResolveIPAddr(%v, %v) failed: %v", tt.net, tt.litAddr, err)
} else if !reflect.DeepEqual(addr, tt.addr) {
t.Fatalf("got %#v; expected %#v", addr, tt.addr)
}
コアとなるコードの解説
このコミットにおけるコアとなるコードの変更は、src/pkg/net/ipraw_test.go
ファイル内のresolveIPAddrTests
スライスへの新しいテストケースの追加と、テスト失敗時のエラー報告方法の変更の2点です。
-
新しいテストケースの追加:
{"ip6:IPv6-ICMP", "::1", &IPAddr{IP: ParseIP("::1")}, nil},
この行が追加されたことで、
TestResolveIPAddr
関数は、net
引数に"ip6:IPv6-ICMP"
という文字列が与えられた場合に、::1
というIPv6アドレスが正しく解決され、エラーが発生しないことを検証するようになります。これは、net.ResolveIPAddr
がプロトコル名のルックアップにおいて、大文字・小文字を区別しない、または少なくとも一般的な大文字・小文字の組み合わせを許容する実装になっていることを確認するための重要なテストです。これにより、ユーザーがプロトコル名を記述する際の大文字・小文字の揺れに対応できるよう、関数の堅牢性が向上します。 -
エラー報告方法の変更:
- condFatalf(t, "ResolveIPAddr(%v, %v) failed: %v", tt.net, tt.litAddr, err) + t.Fatalf("ResolveIPAddr(%v, %v) failed: %v", tt.net, tt.litAddr, err)
この変更は、テストが失敗した場合にエラーメッセージを出力し、テストを終了させるための関数呼び出しを
condFatalf
からt.Fatalf
に直接変更したものです。Goの標準テストパッケージtesting
では、*testing.T
型のメソッドであるFatalf
がテストの失敗を報告し、テストの実行を停止するために使用されます。condFatalf
は、おそらく以前のコードベースで共通のエラー報告ロジックをカプセル化するために使用されていたカスタムヘルパー関数であったと推測されます。この変更は、テストコードをより標準的なGoのテストフレームワークの慣習に合わせるためのリファクタリングであり、機能的な動作に大きな変更はありませんが、コードの可読性と保守性を向上させます。
これらの変更は、net.ResolveIPAddr
関数の堅牢性を高め、様々な入力パターン(特にプロトコル名の大文字・小文字のバリエーション)に対して正しく動作することを保証するためのものです。
関連リンク
参考にした情報源リンク
- Go Code Review:
https://golang.org/cl/12966046
(コミットメッセージに記載されているGoのコードレビューシステムへのリンク) - Go言語
net
パッケージのドキュメント (Goの公式ドキュメントサイト) - Go言語
testing
パッケージのドキュメント (Goの公式ドキュメントサイト) - RFC 2460: Internet Protocol, Version 6 (IPv6) Specification (IPv6に関する一般的な情報)
- RFC 792: Internet Control Message Protocol (ICMPに関する一般的な情報)
- RFC 4443: Internet Control Message Protocol (ICMPv6) for the Internet Protocol Version 6 (IPv6) (ICMPv6に関する一般的な情報)
/etc/protocols
ファイルの一般的な情報 (Unix系システムにおけるプロトコル名と番号のマッピングに関する情報)