Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
internal/testlog で遊ぼう
Search
rokuosan
August 24, 2026
Technology
600
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
internal/testlog で遊ぼう
layerx.go #5 LT
https://layerx.connpass.com/event/402006/
rokuosan
August 24, 2026
More Decks by rokuosan
See All by rokuosan
発見!Ruby 9
rokuosan
0
59
CloudflareのBetaサービスでローカルなLLMを安全に公開する
rokuosan
0
470
Workers を定期実行する方法は一つじゃない
rokuosan
0
580
OpenNext + Hono on Cloudflare でイマドキWeb開発スタックを実現する
rokuosan
0
720
Kotlin で始める MCP 入門
rokuosan
0
360
【学内向け】主観でやるオレオレ RubyKaigi 2025 Recap
rokuosan
0
55
Kotlin で Discord の絵文字コミュニケーションを盛り上げたい!
rokuosan
0
44
ずっと昔に Star をつけたはずの思い出せない GitHub リポジトリを見つけたい!
rokuosan
0
370
KC3 2024 Dockerで始める自宅サーバー入門
rokuosan
0
910
Other Decks in Technology
See All in Technology
オブザーバビリティを高める AI エージェント体験を考える / Designing AI Agent Experiences That Enhance Observability
aoto
PRO
2
310
OSC2026on_the-world-is-waiting-for-your-voice.pdf
naruoga
0
350
SDDの運用にめげずに向き合った話
sansantech
PRO
1
130
メルペイ 会計システム概要と歴史
mewuto
0
170
Execution in the Kingdom of Agents: Reflections on Abstraction and Complexity
bcantrill
0
850
[2026 Oracle Technical Deep Dive] OCI AI Resilience -OCIのセキュリティ対策機能をきちんと使いこなす- (2026年9月17日開催)
oracle4engineer
PRO
0
130
AIアプリを使い分けるための共通ツール基盤を考えてみる#devio2026
osawa
0
260
転んだ話が背中を預ける理由になる / A_story_about_falling_down_gives_you_a_reason_to_watch_each_other_s_backs.pdf
pauli
3
270
[AWS 秋のクラウドオペレーション祭り 2026]AWS DevOps Agentで変わるリリースと運用対応 ~リリース管理機能と Directed actions のご紹介~
furuton
3
950
React Nativeでの OTA Updateって、 どう説明する?
ichiki1023
0
150
AI時代だからこそ推したい!Gitコマンド再入門
munakata
0
150
[2026 Oracle Technical Deep Dive] VMwareワークロードのOCI移行実践ガイド - OCVSでの継続利用からOCIコンピュートへの移行まで (2026年9月17日開催)
oracle4engineer
PRO
0
130
Featured
See All Featured
Code Review Best Practice
trishagee
74
20k
What’s in a name? Adding method to the madness
productmarketing
PRO
24
4.2k
The Myth of the Modular Monolith - Day 2 Keynote - Rails World 2024
eileencodes
28
3.7k
CoffeeScript is Beautiful & I Never Want to Write Plain JavaScript Again
sstephenson
162
16k
Bridging the Design Gap: How Collaborative Modelling removes blockers to flow between stakeholders and teams @FastFlow conf
baasie
0
720
How to build an LLM SEO readiness audit: a practical framework
nmsamuel
2
930
Designing Dashboards & Data Visualisations in Web Apps
destraynor
232
55k
How to build a perfect <img>
jonoalderson
1
6.1k
YesSQL, Process and Tooling at Scale
rocio
174
15k
How To Speak Unicorn (iThemes Webinar)
marktimemedia
1
590
The Art of Programming - Codeland 2020
erikaheidi
57
14k
Fireside Chat
paigeccino
43
4.1k
Transcript
internal/testlog で遊ぼう 2026-08-24 layerx.go #5 @rokuosan_dev
whoami @rokuosan_dev rokuosan(ろくお) id:rokuokun 敬称は省略できます LayerX バクラク事業部 (2026-08 -) Platform
Engineering 部 Enabling チーム インターンです 京都在住 Kyoto.kt 主催 © LayerX Inc.
go test (cached)
緊急 キャッシュされる?されない?クイズ
Q1. 通常の Go test 例えばこんなテスト © LayerX Inc. 5
Q1. 通常の Go test go test を素直に実行する 当然テストが実行される © LayerX
Inc. 6
Q1. 通常の Go test Q1. 2回目は? © LayerX Inc. 7
Q1. 通常の Go test A2. 2回目は cached そうですね © LayerX
Inc. 8
Q2. 依存する環境変数やファイルを変更したテスト Q2. 環境変数やモジュール内のファイルを変更すると? © LayerX Inc. 9
Q2. 依存する環境変数やファイルを変更したテスト A2. 実行される © LayerX Inc. 10
Q3. モジュール外の変更 モジュール外のファイルを参照してみる © LayerX Inc. 11
Q3. モジュール外の変更 Q3. モジュール外のファイルを書き換えたら? © LayerX Inc. 12
Q3. モジュール外の変更 キャッシュされてテストは走らない ファイルを書き換えたのに走らない 困った © LayerX Inc. 13
Q3. モジュール外の変更 強制的に実行させる 無事失敗 © LayerX Inc. 14
cache の仕組み
キャッシュ利用の判定 testID で testlog.txt を取得 testID = テストバイナリの build ID
+ キャッシュ可能な引数 testlog の各行を今の状態でハッシュして inputsID を作る → 現在の値。未設定かどうかも込み open → mtime と size (中身は読まない) stat → Stat と Lstat の結果 GODEBUG はログに出てこなくても必ず混ぜる getenv subkey(testID, inputsID) © LayerX Inc. で前回の出力を取得できれば (cached) ※ subkey(parent, desc) は親キーと説明文字列を混ぜて派生キーを作る cmd/go 共通のヘルパ。stdout や coverprofile の保存にも使われている 16
キャッシュ判定の擬似コード © LayerX Inc. ref: cmd/go/internal/test/test.go tryCacheWithID / computeTestInputsID 17
testlog.txt テストが os 越しに触ったものが、そのまま1行ずつ載る モジュール root の外にあるファイルはログには載るが、ハッシュの対象にならない フォーマットについては後述 © LayerX
Inc. 18
internal/testlog
internal/testlog Package testlog provides a back-channel communication path between tests
and package os, so that cmd/go can see which environment variables and files a test consults. テストと os の間のバックチャネル cmd/go testing が「テストがどの env / file を見たか」を知るためにある が実装を挿し、 os がそれを呼ぶ 両者が共通で依存できる最下層に置かれている © LayerX Inc. ref: https://github.com/golang/go/blob/go1.26.7/src/internal/testlog/log.go#L5-L7 20
Interface os © LayerX Inc. 側は testlog.Open(name) と呼ぶだけ logger が
nil なら何もしない ※ atomic.Pointer なのは、init で起きた goroutine と競合しても race detector に引っかからないようにするため 21
internal/testlog を自作する
Interface を用意する 同じメソッドを同じシグネチャで並べた interface を自前で定義する internal/testlog.Interface © LayerX Inc. は
internal なため... 23
フォーマットにそって実装する 1行目は # test log で固定 これが無いと malformed 扱いで丸ごと捨てられる あとは
op name を1行ずつ。末尾は必ず改行 op は open / stat / getenv / chdir の4つだけ © LayerX Inc. ref: cmd/go/internal/test/test.go testlogMagic 24
どうやって動かす? © LayerX Inc. 25
go:linkname による差し込み 本体の無い関数を宣言して、リンカに繋がせる 実体は internal/testlog.SetLogger 渡すのはさっきの自前 interface © LayerX Inc.
26
敗北... Go 1.23 以降のリンカの制限 定義側にマークが無いシンボルは引けない -ldflags=-checklinkname=0 © LayerX Inc. で黙らせる
27
checklinkname=0 でも敗北... SetLogger © LayerX Inc. は一度しか呼び出せない ref: https://github.com/golang/go/blob/go1.26.7/src/testing/internal/testdeps/deps.go#L117-L130 28
SetLogger を呼ぶ経路 © LayerX Inc. ref: https://github.com/golang/go/blob/go1.26.7/src/testing/testing.go#L2600-L2680 29
SetLogger を呼ぶ経路 -test.testlogfile © LayerX Inc. は go test が毎回付けてくる
cmd/go がテストバイナリの os.Args を組み立てている *testlog はその値を flag.Parse が受け取ったもの ref: https://github.com/golang/go/blob/go1.26.7/src/testing/testing.go#L2600-L2680 30
SetLogger を呼ぶ経路 ここで一度目の SetLogger が呼ばれる さっきの panic はここと衝突 © LayerX
Inc. ref: https://github.com/golang/go/blob/go1.26.7/src/testing/testing.go#L2600-L2680 31
SetLogger を呼ぶ経路 ここを false のままにしたい os.Args © LayerX Inc. から
-test.testlogfile を消せば、この経路ごと実行されない ref: https://github.com/golang/go/blob/go1.26.7/src/testing/testing.go#L2600-L2680 32
SetLogger を呼ぶ経路 init © LayerX Inc. で os.Args を書き換えると良さそう ref:
https://github.com/golang/go/blob/go1.26.7/src/testing/testing.go#L2600-L2680 33
os.Args の書き換えと Logger の置き換え を空文字にしてデフォルトの testlog を無効化 独自実装の testlog を差し込む
*testlog © LayerX Inc. 34
自作 testlog を仕込む
blank import による利用 で書いたのでこれで完了 ただしパッケージ単位... init() 差し替えたい全パッケージに1行ずつ書く必要がある © LayerX Inc.
36
overlay による差し込み -overlay © LayerX Inc. は存在しないパスを実ファイルに割り当てられる 37
差し込んでみる © LayerX Inc. 38
実行してみる © LayerX Inc. 39
ここからが本題
自作 testlog で遊んでみる © LayerX Inc. 41
GitHub Actions で (cached) 出ない問題 checkout のたびに全ファイルの mtime が更新される キャッシュを復元しても無駄
中身ではなく mtime で判定しているため golang/go にも issue がある golang/go #58571 © LayerX Inc. ref: golang/go#58571 「cmd/go: test cache hash inputs include ModTime, often causing cache misses on CI」 42
mtime はどこでハッシュに入るか(1/2) / mode / mtime / isdir をハッシュに書く #58571
でも言及されている size © LayerX Inc. ref: https://github.com/golang/go/blob/go1.26.7/src/cmd/go/internal/test/test.go#L2138-L2140 43
mtime はどこでハッシュに入るか(2/2) これを実行すると以下の testlog が出る cmd/go はこの行を見て os.Stat し、実ファイルの mtime
をハッシュに混ぜる これによって checkout のたびに実ファイルの mtime は新品になる © LayerX Inc. 44
余談: なぜ中身ではなく mtime なのか 中身を丸ごとハッシュしない 巨大なファイルを毎回読むコストを避けるため 代わりに mtime + size
で「たぶん変わっていない」を推測する 正確だが遅い方法を捨てて、速いが不正確な方法を選んでいる © LayerX Inc. ref: https://github.com/golang/go/blob/go1.26.7/src/cmd/go/internal/test/test.go#L2107-L2110 45
中身が変わったものだけ mtime が動いてほしい © LayerX Inc. 46
自作 testlog で見る先をすり替える testlog.txt は扱えるようになった 実ファイルの代わりに、中身が変わった時だけ mtime が動く代理ファイルを指すよう に書き換える test
実行前に中身が更新されていたら上書きする © LayerX Inc. 47
余談: なぜ open ではなく stat で書くか hashOpen では2秒以内に更新されたファイルの結果を保存しない仕様がある mtime の精度ではごく短い間隔の更新を区別できないことがあるため
© LayerX Inc. ref: https://github.com/golang/go/blob/go1.26.7/src/cmd/go/internal/test/test.go#L2112-L2118 48
こんな感じ テスト実行前に生成を忘れると破滅することには注意 古いハッシュを見続けるためずっと OK のまま © LayerX Inc. 49
まとめ (cached) は中身ではなくサイズや mtime で判断している internal/testlog を通じて、前回何を触ったかが記録されている internal package でも
linkname と overlay で挙動を変更できる GitHub Actions で別ジョブを跨ぐと go test は cached にならない checkout のたびに mtime が新品になるため 自作 testlog を使えば常に成功する go test を爆誕させることも可能 © LayerX Inc. 50