tasty-discover が Windows+日本語環境で動かなかったので直す
おそらく少数派であろう Windows + 日本語環境の Haskeller のひげです.
最近は知人のすゝめで,Haskell のテストフレームワークに tasty
を使ってます. tasty
にも例に漏れず tasty-discover
というテスト用の関数を .hs
ファイルから集めてきてくれるツールがある. しかし,悲しいことに tasty-discover
がマルチバイト文字(日本語とか)を Windows で読み込むと いつもの エラーで死んでしまう.
なので,直して PR 出した. この記事はそのメモです.
2018.11.18 追記
tasty-discover はたしか GitHub が MS に買収されたあたりに,git.coop に移行された. なので,リンクなどが間違っていたらすいません.
問題のエラー
Building test suite 'test' for tasty-discover-4.1.3..
tasty-discover: test\ConfigTest.hs: hGetContents: invalid argument (invalid byte sequence)
`tasty-discover' failed in phase `Haskell pre-processor'. (Exit code: 1)
Progress: 1/2
-- While building custom Setup.hs for package tasty-discover-4.1.3 using:
C:\Users\Hoge\AppData\Roaming\stack\setup-exe-cache\i386-windows\Cabal-simple_Z6RU0evB_2.0.1.0_ghc-8.2.2.exe --builddir=.stack-work\dist\010ee936 build lib:tasty-discover exe:tasty-discover test:test --ghc-options " -ddump-hi -ddump-to-file -fdiagnostics-color=always"
Process exited with code: ExitFailure 1
hGetContents: invalid argument (invalid byte sequence)
は 日本語 Windows Haskeller なら親の顔より良く見るエラーメッセージですね(そんなことは無い). このエラーは hGetContents
で読み込もうとしているファイルの文字コードが,hGetContents
で設定されている文字コードと違うために起きている(hGetContents
関数は,例えば readFile
関数などで呼び出されている).
対処法
日本語 Windows Haskeller 筆頭の igrep 氏が Haskell-jp Blog に投稿してくれてる.
今回は(孫プロセスとして読んでるせいか)「それでもダメな場合」に当たる. つまり,場当たり的な解決方法(chcp 65001
と打つとか)ではダメで,プログラムを修正するしかない.
神な igrep 氏は,この場合の解決策も書いておいてくれた. この PR を参考にして書き換えてやればよい.
tasty-discover
もこんな感じに書き加えた.
PR を出す
修正自体は1時間ほどで終わり(移動中の新幹線の中で直した),これでテストを実行できるようになったので PR を出さずに満足してしまった(あるある). 半月ほどほっといてたら,同じケースで困った知り合いに Issue を出されてしまった(笑)
しょうがないので PR を出そうとしたら,「Windows は良く分からないから,ぜひ Windows 環境用の自動テストも欲しい!」と作者に言われてしまった(「時間があればやって」とね).
AppVeyor と言うのを使えばいいみたい. 調べたらサクッとできそうなので,やってみた.
記事にある設定ファイルをそのままコピペしてやってみたが,問題がふたつあった. ひとつ目は,tasty-discover
のテスト自体に tasty-discover
を使っている点だ. 最初に stack test
を実行するときにはまだ tasty-discover
はインストールされてないのでテストが落ちてしまう.
[2 of 2] Compiling Paths_tasty_discover ( .stack-work\dist\010ee936\build\tasty-discover\autogen\Paths_tasty_discover.hs, .stack-work\dist\010ee936\build\tasty-discover\tasty-discover-tmp\Paths_tasty_discover.o )
Linking .stack-work\dist\010ee936\build\tasty-discover\tasty-discover.exe ...
Preprocessing test suite 'test' for tasty-discover-4.1.3..
Building test suite 'test' for tasty-discover-4.1.3..
ghc.EXE: could not execute: tasty-discover
なので,stack test
する前に stack install
することにした.
ふたつ目は,そもそも WIndows のビルドが落ちる点. System.FilePath
に関するバグだったので,サクッと直した. Windows のテストに関する PR もマージされたので,本命の PR も出した(これもマージされた).
今回の問題をテストする(?)
今回の問題のテストも欲しいと言われた. tasty-discover
のテスト自体が tasty-discover
を使うため,ユニットテストとして表現できない. stack test
そのものが落ちるか落ちないかのテストはできるが,それはなんか違うなぁと思い,結局コミットはしていない.
ただし,いちおう AppVeyor で再現できるようにはした. AppVeyor はデフォルトだと日本語環境になっていない(即ち Shift-JIS じゃない)ため落ちない. なので,以下を参考にして日本語環境にして実行した.
init:
- ps: Set-WinSystemLocale ja-JP
- ps: Start-Sleep -s 5
- ps: Restart-Computer
というのを appveyor.yml
に書き加えるだけで良い.
おしまい
なんか Push 権限を貰った. こういうこともあるんですね(OSS歴が浅いので驚いた).