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

[インデックス 102] ファイルの概要

コミット

このコミットは、Go言語の初期開発段階におけるテストスイートの拡張と、テスト実行スクリプトの改善を目的としています。具体的には、test/ken/ ディレクトリに多数の新しいテストケースが追加され、既存の test/golden.out ファイルが更新され、test/run スクリプトが複数のディレクトリで動作するように修正されています。

GitHub上でのコミットページへのリンク

https://github.com/golang/go/commit/ab34d15f69de4e5b3330b43e23f99bf3ee2ed10a

元コミット内容

add ken's tests.
update run to work with multiple directories

SVN=121485

変更の背景

このコミットは、Go言語の初期段階において、言語の機能が拡張され、より複雑な挙動が導入されるにつれて、テストカバレッジを向上させる必要があったことを示唆しています。特に「Ken's tests」という記述から、Go言語の共同設計者の一人であるKen Thompson氏が作成したテストケースが追加されたことがわかります。これは、言語の設計思想や初期の意図を反映した、重要なテスト群であったと考えられます。

また、「update run to work with multiple directories」という変更は、テストスイートが大規模化し、テストファイルが複数のディレクトリに分散されるようになったことに対応するためのものです。これにより、テストの管理と実行がより柔軟かつ効率的に行えるようになったと推測されます。

前提知識の解説

  • Go言語の初期開発: Go言語は、Googleによって2007年後半に設計が開始され、2009年にオープンソースとして公開されました。このコミットの日付(2008年6月6日)から、Go言語がまだ活発な開発段階にあり、基本的な言語機能の確立と安定化が進められていた時期であることがわかります。
  • テスト駆動開発 (TDD): ソフトウェア開発において、コードを書く前にテストケースを作成し、そのテストが通るようにコードを実装する開発手法です。Go言語の設計者たちは、堅牢な言語とランタイムを構築するために、初期から徹底したテストを重視していました。
  • test/golden.out: 多くのプロジェクトで用いられる「ゴールデンファイルテスト」の一種です。これは、プログラムの出力(この場合はコンパイラやランタイムの出力、またはテストプログラム自体の出力)を事前に「正しい」とされるファイル(ゴールデンファイル)に保存しておき、テスト実行時に生成される出力と比較することで、予期せぬ変更やバグを検出する手法です。
  • test/run スクリプト: Go言語のテストスイートを実行するためのシェルスクリプトまたは同様の実行ファイルです。初期のGo言語では、ビルドシステムやテストランナーが現在ほど洗練されていなかったため、このようなカスタムスクリプトがテストの自動化に用いられていました。
  • Ken Thompson: Go言語の共同設計者の一人であり、UNIX、B言語、UTF-8などの開発で知られる計算機科学のパイオニアです。彼が作成したテストは、言語の根幹に関わる重要な機能の検証を目的としていた可能性が高いです。

技術的詳細

このコミットは、主に以下の2つの側面で技術的な変更を加えています。

  1. 新しいテストケースの追加:

    • test/ken/ ディレクトリ以下に、for.go, interfun.go, intervar.go, label.go, litfun.go, mfunc.go, ptrfun.go, ptrvar.go, rob1.go, rob2.go, robfor.go, robfunc.go, robif.go, robiota.go, robliteral.go, robswitch.go, simparray.go, simpbool.go, simpconv.go, simpfun.go, simpprint.go, simpswitch.go, simpvar.go, string.go, strvar.go といった多数のGoソースファイルが追加されています。
    • これらのファイルは、Go言語の様々な機能(ループ、関数、インターフェース、ポインタ、ラベル、リテラル、スイッチ文、配列、ブール演算、型変換、文字列操作など)を網羅的にテストしていることがファイル名から推測できます。
    • 各テストファイルには、// $G $D/$F.go && $L $F.$A && ./$A.out のようなコメントが含まれており、これはGoコンパイラ ($G) でコンパイルし、リンカ ($L) でリンクし、実行可能ファイル (./$A.out) を実行するという、当時のテスト実行コマンドのパターンを示しています。
    • 多くのテストファイルには panic を用いたアサーションが含まれており、期待される結果と異なる場合にプログラムを異常終了させることで、テストの失敗を検出しています。
  2. テスト実行スクリプト test/run の更新:

    • test/run スクリプトは、複数のディレクトリにあるテストファイルを処理できるように変更されました。これは、テストスイートの規模が拡大し、テストケースが論理的にグループ化されて複数のサブディレクトリに配置されるようになったことに対応するためです。
    • 具体的な変更内容はコミットログからは読み取れませんが、おそらくテスト対象のディレクトリを引数として受け取ったり、特定のパターンにマッチするファイルを再帰的に検索したりする機能が追加されたと考えられます。
    • test/golden.out の変更は、新しいテストが追加されたことによって、テスト実行時の標準出力やエラー出力が変化したことを反映しています。特に、ファイルパスが ./char_lit.go のように相対パスで記述されるようになった点が注目されます。これは、test/run スクリプトがテストファイルを特定のディレクトリ内で実行するようになったことと関連している可能性があります。

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

このコミットのコアとなる変更は、以下のファイル群の追加と変更です。

  • test/golden.out: 既存のゴールデンファイルが更新され、新しいテストの出力が反映されています。特に、ファイルパスの記述形式が変更されています。
    • -=========== char_lit.go+=========== ./char_lit.go に変更されるなど、テスト対象ファイルのパスに ./ が追加されています。
    • test/ken/ 以下に追加された各テストファイルのエントリが追加されています。
  • test/ken/ ディレクトリ以下の新規追加ファイル:
    • test/ken/for.go
    • test/ken/interfun.go
    • test/ken/intervar.go
    • test/ken/label.go
    • test/ken/litfun.go
    • test/ken/mfunc.go
    • test/ken/ptrfun.go
    • test/ken/ptrvar.go
    • test/ken/rob1.go
    • test/ken/rob2.go
    • test/ken/robfor.go
    • test/ken/robfunc.go
    • test/ken/robif.go
    • test/ken/robiota.go
    • test/ken/robliteral.go
    • test/ken/robswitch.go
    • test/ken/simparray.go
    • test/ken/simpbool.go
    • test/ken/simpconv.go
    • test/ken/simpfun.go
    • test/ken/simpprint.go
    • test/ken/simpswitch.go
    • test/ken/simpvar.go
    • test/ken/string.go
    • test/ken/strvar.go
  • test/run: テスト実行スクリプトが変更され、複数のディレクトリに対応できるようになりました。

コアとなるコードの解説

ここでは、追加されたテストファイルの中からいくつかピックアップして、その内容と意図を解説します。

test/ken/for.go

// $G $D/$F.go && $L $F.$A && ./$A.out

// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.


package main

func
main()
{
	var t,i int;

	for i=0; i<100; i=i+1 {
		t = t+i;
	}
	if t != 50*99  { panic t; }
}

このテストは、Go言語の for ループの基本的な動作を検証しています。i を0から99までインクリメントしながら t に加算していき、最終的な t の値が 50*99 (つまり0から99までの合計値) と一致するかを確認しています。これは、ループの初期化、条件、更新式、およびループ本体の実行が正しく行われることを保証するための基本的なテストです。

test/ken/interfun.go

// $G $D/$F.go && $L $F.$A && ./$A.out

// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package main

type S struct
{
	a,b	int;
}

type I1 interface
{
	f	()int;
}

type I2 interface
{
	g,f	()int;
}

func
(this *S) f()int
{
	return this.a;
}

func
(this *S) g()int
{
	return this.b;
}

func
main()
{
	var i1 I1;
	var i2 I2;
	var g *S;

	s := new(S);
	s.a = 5;
	s.b = 6;

	// call structure
	if s.f() != 5 { panic 11; }
	if s.g() != 6 { panic 12; }

	i1 = s;		// convert S to I1
	i2 = i1;	// convert I1 to I2

	// call interface
	if i1.f() != 5 { panic 21; }
	if i2.f() != 5 { panic 22; }
	if i2.g() != 6 { panic 23; }

	g = i1;		// convert I1 to S
	if g != s { panic 31; }

	g = i2;		// convert I2 to S
	if g != s { panic 32; }
}

このテストは、Go言語のインターフェースの基本的な動作、特に型アサーションとインターフェース間の変換を検証しています。

  • S という構造体が f()g() というメソッドを持ちます。
  • I1f() メソッドを持つインターフェース、I2f()g() メソッドを持つインターフェースです。
  • S のインスタンスが I1I2 インターフェースに正しく変換できるか、そしてインターフェースを介してメソッドが正しく呼び出せるかを確認しています。
  • さらに、インターフェース型から元の具象型 (*S) への型アサーションが正しく行われるかも検証しています。

これは、Go言語の重要な特徴であるインターフェースの多態性が正しく機能することを保証するためのテストです。

test/ken/robliteral.go

// Copyright 2009 The Go Authors.  All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// $G $D/$F.go && $L $F.$A && ./$A.out

package main

func assert(cond bool, msg string) {
	if !cond {
		print "assertion fail: " + msg + "\n";
		//panic 1;  this file has errors; print them all
	}
}

func main() {
	// bool
	var t bool = true;
	var f bool = false;
	assert(t == !f, "bool");

	// int8
	var i00 int8 = 0;
	var i01 int8 = 1;
	// ... (各種整数型、浮動小数点型、文字、文字列のリテラルテスト)
}

このテストは、Go言語における様々なリテラル(真偽値、整数、浮動小数点数、文字、文字列)の正しい解釈と表現を検証しています。

  • bool 型の truefalse のリテラルが正しく扱われるか。
  • int8, int16, int32, int64, uint8, uint16, uint32, uint64 といった各種整数型のリテラルが、その範囲内で正しく表現され、演算が機能するか。特に、最大値、最小値、負の値などが含まれています。
  • float 型の浮動小数点数リテラルが、様々な形式(指数表記、小数点のみなど)で正しく解釈されるか。
  • 文字リテラルが、通常の文字、エスケープシーケンス、Unicode文字などで正しく表現されるか。
  • 文字列リテラルが、生文字列リテラル(バッククォート)、引用符付き文字列リテラル、各種エスケープシーケンス、Unicode文字などで正しく表現されるか。

このテストは、Goコンパイラが言語仕様に厳密に従ってリテラルを解析し、内部表現に変換できることを保証するために非常に重要です。

test/run の変更

test/run スクリプト自体の具体的な変更内容はコミットログからは読み取れませんが、test/golden.out の変更から、テスト対象のファイルパスが ./ を含む形式に変わったことがわかります。これは、test/run スクリプトが、テストを実行する際にカレントディレクトリをテストファイルが存在するディレクトリに移動させるか、あるいはテストファイルのパスを相対パスとして解釈するように変更されたことを示唆しています。これにより、テストスイートの構造がより柔軟になり、テストファイルを複数のサブディレクトリに整理することが可能になりました。

関連リンク

参考にした情報源リンク

  • Go言語のコミット履歴 (GitHub): https://github.com/golang/go/commit/ab34d15f69de4e5b3330b43e23f99bf3ee2ed10a
  • Go言語の歴史に関する情報 (公式ドキュメントやブログなど)
  • Ken Thompsonに関する情報 (Wikipediaなど)
  • ゴールデンファイルテストに関する一般的な情報 (ソフトウェアテストの文献など)
  • Go言語の言語仕様 (初期のバージョンに関する情報があれば尚良い)
  • Go言語のテストに関するドキュメント