From 6dda7298e06cffff0a39a9b047c8f032c9703035 Mon Sep 17 00:00:00 2001 From: tsuchinaga Date: Mon, 13 Jul 2020 11:42:15 +0900 Subject: [PATCH 1/2] =?UTF-8?q?io.Reader=E3=81=A8io.Writer=E3=81=AB?= =?UTF-8?q?=E3=81=A4=E3=81=84=E3=81=A6=E8=AA=BF=E3=81=B9=E3=81=A6=E3=81=BF?= =?UTF-8?q?=E3=82=88=E3=81=86=20=E3=81=AE=E5=9B=9E=E7=AD=94=E3=82=92README?= =?UTF-8?q?=E3=81=AB=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- kadai2/tsuchinaga/.gitignore | 4 +++ kadai2/tsuchinaga/README.md | 56 ++++++++++++++++++++++++++++++++++++ 2 files changed, 60 insertions(+) create mode 100644 kadai2/tsuchinaga/.gitignore create mode 100644 kadai2/tsuchinaga/README.md diff --git a/kadai2/tsuchinaga/.gitignore b/kadai2/tsuchinaga/.gitignore new file mode 100644 index 0000000..3e400d7 --- /dev/null +++ b/kadai2/tsuchinaga/.gitignore @@ -0,0 +1,4 @@ +## for IntelliJ +.idea +*.iml + diff --git a/kadai2/tsuchinaga/README.md b/kadai2/tsuchinaga/README.md new file mode 100644 index 0000000..582abb7 --- /dev/null +++ b/kadai2/tsuchinaga/README.md @@ -0,0 +1,56 @@ +# 課題2 tsuchinaga + +## 課題 +スライドより転載 + +* io.Readerとio.Writerについて調べてみよう + * 標準パッケージでどのように使われているか + * io.Readerとio.Writerがあることで + どういう利点があるのか具体例を挙げて考えてみる +* 1回目の課題のテストを作ってみて下さい + * テストのしやすさを考えてリファクタリングしてみる + * テストのカバレッジを取ってみる + * テーブル駆動テストを行う + * テストヘルパーを作ってみる + + +### io.Readerとio.Writerについて調べてみよう + +`io.Reader` と `io.Writer` を実装している代表的なのはやはり `os.File` だと思う。 + +`os.File` には `os.Stdin` 、 `os.Stdout` 、 `os.Stderr` がある。 +これらはそれぞれ、標準入力、標準出力、標準エラーにあたり、誰もが入出力先にしたことがあると思う。 + +例えば、「出力先を標準出力からログファイルにかえたいなー」というときに、 +`io.Writer` がなければ新たに出力用の処理を用意して上げる必要があったり、 +標準ライブラリが `io.Writer` を出力先に指定していなければ、標準ライブラリと同じことをするのに自前で用意する必要があったりする。 +さらに、「標準出力とログファイルの両方に出したいなー」みたいなときに、それぞれを同じように扱えるようにしていないと処理を作ることも難しい。 + +読み込みの代表例として、 `bufio.Scanner` をあげる。 + +競技プログラミングで大きな入力を受け取るときや、サイズの大きいファイルを読み込むときにお世話になる。 +※ 他にも1単語ずつじゃなくて、1行ずつ読むときとかにも重宝する + +この `Scanner` を生成する関数である `NewScanner` は下記のようになっている。 +```go +// NewScanner returns a new Scanner to read from r. +// The split function defaults to ScanLines. +func NewScanner(r io.Reader) *Scanner { + return &Scanner{ + r: r, + split: ScanLines, + maxTokenSize: MaxScanTokenSize, + } +} +``` +引数が `io.Reader` となっている。 +これは標準入力だろうが、ファイルだろうが、HTTPリクエストのBodyだろうが、なんでもかんでも同じように扱える。 + +同じような処理をいっぱい作らなくていい以外に、モックを作りやすいというメリットもある。(interfaceのメリットかも) + +テストコードを書いていると、ここなんか適当なもので置き換えたいなーというのは頻繁にある。 +そんな時に構造体に依存していたりすると置き換えることができず、密結合が起きてしまい、テストしづらくなる。 +そこをinterfaceに依存するようにしていると、置き換えることが容易になる。 + + +### 1回目の課題のテストを作ってみて下さい From cbaf2f7db7663b9bcb30670d3b3bf9b51a4c6f41 Mon Sep 17 00:00:00 2001 From: tsuchinaga Date: Tue, 14 Jul 2020 12:47:08 +0900 Subject: [PATCH 2/2] =?UTF-8?q?=E3=83=86=E3=82=B9=E3=83=88=E3=82=92?= =?UTF-8?q?=E6=9B=B8=E3=81=8D=E3=81=AA=E3=81=8C=E3=82=89=E7=94=BB=E5=83=8F?= =?UTF-8?q?=E5=A4=89=E6=8F=9B=E3=82=92=E5=AE=9F=E8=A3=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- kadai2/tsuchinaga/.gitignore | 2 + kadai2/tsuchinaga/README.md | 44 +++ kadai2/tsuchinaga/go.mod | 5 + kadai2/tsuchinaga/go.sum | 2 + kadai2/tsuchinaga/imgconv/imgconv.go | 181 ++++++++++++ kadai2/tsuchinaga/imgconv/imgconv_test.go | 272 ++++++++++++++++++ kadai2/tsuchinaga/main.go | 54 ++++ kadai2/tsuchinaga/testdata/Example.jpg | Bin 0 -> 9022 bytes kadai2/tsuchinaga/testdata/Example.png | Bin 0 -> 2335 bytes kadai2/tsuchinaga/testdata/Example.txt | 1 + kadai2/tsuchinaga/testdata/Example.xlsx | Bin 0 -> 8358 bytes .../tsuchinaga/testdata/subdir1/Example.jpg | Bin 0 -> 9022 bytes .../tsuchinaga/testdata/subdir1/Example.png | Bin 0 -> 2335 bytes .../testdata/subdir1/subdir1_1/Example.jpg | Bin 0 -> 9022 bytes .../subdir1/subdir1_1/subdir1_1_1/Example.png | Bin 0 -> 2335 bytes .../testdata/subdir2/subdir2_1/Example.jpg | Bin 0 -> 9022 bytes .../testdata/subdir2/subdir2_1/Example.png | Bin 0 -> 2335 bytes kadai2/tsuchinaga/validation/validation.go | 38 +++ .../tsuchinaga/validation/validation_test.go | 116 ++++++++ 19 files changed, 715 insertions(+) create mode 100644 kadai2/tsuchinaga/go.mod create mode 100644 kadai2/tsuchinaga/go.sum create mode 100644 kadai2/tsuchinaga/imgconv/imgconv.go create mode 100644 kadai2/tsuchinaga/imgconv/imgconv_test.go create mode 100644 kadai2/tsuchinaga/main.go create mode 100644 kadai2/tsuchinaga/testdata/Example.jpg create mode 100644 kadai2/tsuchinaga/testdata/Example.png create mode 100644 kadai2/tsuchinaga/testdata/Example.txt create mode 100644 kadai2/tsuchinaga/testdata/Example.xlsx create mode 100644 kadai2/tsuchinaga/testdata/subdir1/Example.jpg create mode 100644 kadai2/tsuchinaga/testdata/subdir1/Example.png create mode 100644 kadai2/tsuchinaga/testdata/subdir1/subdir1_1/Example.jpg create mode 100644 kadai2/tsuchinaga/testdata/subdir1/subdir1_1/subdir1_1_1/Example.png create mode 100644 kadai2/tsuchinaga/testdata/subdir2/subdir2_1/Example.jpg create mode 100644 kadai2/tsuchinaga/testdata/subdir2/subdir2_1/Example.png create mode 100644 kadai2/tsuchinaga/validation/validation.go create mode 100644 kadai2/tsuchinaga/validation/validation_test.go diff --git a/kadai2/tsuchinaga/.gitignore b/kadai2/tsuchinaga/.gitignore index 3e400d7..e6e6285 100644 --- a/kadai2/tsuchinaga/.gitignore +++ b/kadai2/tsuchinaga/.gitignore @@ -2,3 +2,5 @@ .idea *.iml +testdata/**/*.converted.* +cover.out diff --git a/kadai2/tsuchinaga/README.md b/kadai2/tsuchinaga/README.md index 582abb7..f814726 100644 --- a/kadai2/tsuchinaga/README.md +++ b/kadai2/tsuchinaga/README.md @@ -54,3 +54,47 @@ func NewScanner(r io.Reader) *Scanner { ### 1回目の課題のテストを作ってみて下さい + +リファクタリングの域をこえてるきもするけど、いつもやってるようにTODO出してテストを作っていく +課題1の時よりも責務を意識してTODOを分ける + +* [x] ディレクトリが指定でき、その配下のディレクトリとファイルを再帰的に探索し、変換前として指定されたフォーマットの画像ファイルを変換後として指定されたフォーマットの画像ファイルに変換する + * [x] コマンドのパラメータを指定する + * [x] ベースのディレクトリを指定する + * [x] 必須 + * [x] 変換前のファイルフォーマットを指定する + * [x] 任意 + * [x] デフォルトjpeg + * [x] 許容されるのはjpeg/png + * [x] 変換後のファイルフォーマットを指定する + * [x] 任意 + * [x] デフォルトpng + * [x] 許容されるのはjpeg/png + * [x] 変換前と同じフォーマットの指定は不可 + * [x] 指定されたディレクトリの配下のディレクトリとファイルの一覧を取得する + * [x] 配下にディレクトリがあればさらに読み込めるようにする + * [x] 指定されたパスがディレクトリでなければ中止 + * [x] ディレクトリかを判断する + * [x] ファイルの画像フォーマットを取得する + * [x] ファイルが画像なら画像フォーマットを取得する + * [x] ファイルが画像でなければフォーマットは取得できないので中止 + * [x] ファイルフォーマットを変換する + + +#### カバレッジ +```bash +$ go tool cover -func=cover.out +github.com/gopherdojo/dojo8/kadai2/tsuchinaga/imgconv/imgconv.go:27: NewIMGConverter 100.0% +github.com/gopherdojo/dojo8/kadai2/tsuchinaga/imgconv/imgconv.go:42: Do 93.3% +github.com/gopherdojo/dojo8/kadai2/tsuchinaga/imgconv/imgconv.go:74: NewConverter 100.0% +github.com/gopherdojo/dojo8/kadai2/tsuchinaga/imgconv/imgconv.go:90: IsDir 100.0% +github.com/gopherdojo/dojo8/kadai2/tsuchinaga/imgconv/imgconv.go:99: GetIMGType 90.0% +github.com/gopherdojo/dojo8/kadai2/tsuchinaga/imgconv/imgconv.go:118: DirFileList 100.0% +github.com/gopherdojo/dojo8/kadai2/tsuchinaga/imgconv/imgconv.go:137: Convert 69.2% +github.com/gopherdojo/dojo8/kadai2/tsuchinaga/validation/validation.go:4: NewValidator 100.0% +github.com/gopherdojo/dojo8/kadai2/tsuchinaga/validation/validation.go:19: IsValidDir 100.0% +github.com/gopherdojo/dojo8/kadai2/tsuchinaga/validation/validation.go:26: IsValidFileType 100.0% +github.com/gopherdojo/dojo8/kadai2/tsuchinaga/validation/validation.go:31: IsValidSrc 100.0% +github.com/gopherdojo/dojo8/kadai2/tsuchinaga/validation/validation.go:36: IsValidDest 100.0% +total: (statements) 86.1% +``` diff --git a/kadai2/tsuchinaga/go.mod b/kadai2/tsuchinaga/go.mod new file mode 100644 index 0000000..f5adc6d --- /dev/null +++ b/kadai2/tsuchinaga/go.mod @@ -0,0 +1,5 @@ +module github.com/gopherdojo/dojo8/kadai2/tsuchinaga + +go 1.14 + +require golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 diff --git a/kadai2/tsuchinaga/go.sum b/kadai2/tsuchinaga/go.sum new file mode 100644 index 0000000..3ab73ea --- /dev/null +++ b/kadai2/tsuchinaga/go.sum @@ -0,0 +1,2 @@ +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= diff --git a/kadai2/tsuchinaga/imgconv/imgconv.go b/kadai2/tsuchinaga/imgconv/imgconv.go new file mode 100644 index 0000000..fc98492 --- /dev/null +++ b/kadai2/tsuchinaga/imgconv/imgconv.go @@ -0,0 +1,181 @@ +package imgconv + +import ( + "fmt" + "image" + "image/jpeg" + "image/png" + "io/ioutil" + "os" + "path" + + "golang.org/x/xerrors" +) + +var ( + ReadDirError = xerrors.New("read dir error") + FileStatError = xerrors.New("file stat error") + OpenFileError = xerrors.New("open file error") + CloseFileError = xerrors.New("close file error") + NotImageError = xerrors.New("not image error") + ReadImageError = xerrors.New("read image error") + CreateDestinationFileError = xerrors.New("create destination file error") + EncodeImageError = xerrors.New("encode image error") +) + +// NewIMGConverter - 新しい画像変換の生成 +func NewIMGConverter() IMGConverter { + return &imgConverter{converter: NewConverter()} // converterを外からもらってもいいけど、使い方は決まってるので決め打ちで +} + +// IMGConverter - 画像変換のユースケースのインターフェース +type IMGConverter interface { + Do(path, src, dest string) chan error +} + +// imgConverter - 画像変換のユースケース +type imgConverter struct { + converter Converter +} + +// Do - 指定されたディレクトリから再帰的にたどりながらファイルを変換する +func (c *imgConverter) Do(path, src, dest string) chan error { + ch := make(chan error) + + go func() { + defer close(ch) + + dirs, files, err := c.converter.DirFileList(path) + if err != nil { + ch <- err + return + } + + // 非同期で再帰的にディレクトリをたどる + for _, dir := range dirs { + dch := c.Do(dir, src, dest) + for err := range dch { + ch <- err + } + } + + // ファイルを変換する + for _, file := range files { + if err := c.converter.Convert(file, src, dest); err != nil { + ch <- err + } + } + }() + + return ch +} + +// NewConverter - 新しいConverterを生成する +func NewConverter() Converter { + return &converter{} +} + +// converter - 変換処理とそれに付随する処理をもつサービスのインターフェース +type Converter interface { + IsDir(path string) (bool, error) + GetIMGType(path string) (_ string, err error) + DirFileList(filePath string) ([]string, []string, error) + Convert(filePath string, src string, dest string) (err error) +} + +// converter - 変換処理とそれに付随する処理をもつサービス +type converter struct{} + +// IsDir - pathがディレクトリかどうか +func (c converter) IsDir(path string) (bool, error) { + fi, err := os.Stat(path) + if err != nil { + return false, xerrors.Errorf("%+v: %w", err, FileStatError) + } + return fi.IsDir(), nil +} + +// GetIMGType - 引数のファイルの画像フォーマットを取得する +func (c converter) GetIMGType(path string) (_ string, err error) { + f, err := os.Open(path) + if err != nil { // 開けない + return "", OpenFileError + } + defer func() { + if closeErr := f.Close(); closeErr != nil { + err = xerrors.Errorf("%+v: %w", closeErr, CloseFileError) + } + }() + + _, format, err := image.DecodeConfig(f) + if err != nil { // 画像じゃない + return "", NotImageError + } + return format, nil +} + +// DirFileList - 引数直下のディレクトリとファイルの配列を返す +func (c converter) DirFileList(filePath string) ([]string, []string, error) { + infos, err := ioutil.ReadDir(filePath) + if err != nil { + return nil, nil, xerrors.Errorf("%+v(filePath: %s): %w", err, filePath, ReadDirError) + } + + dirs, files := make([]string, 0), make([]string, 0) + for _, info := range infos { + jp := path.Join(filePath, info.Name()) + if info.IsDir() { + dirs = append(dirs, jp) + } else { + files = append(files, jp) + } + } + return dirs, files, nil +} + +// Convert - 画像変換 +func (c converter) Convert(filePath string, src string, dest string) (err error) { + if ft, err := c.GetIMGType(filePath); err != nil { + return err + } else if ft != src { + return nil + } + + f, err := os.Open(filePath) + if err != nil { // 開けない + return xerrors.Errorf("%+v: %w", err, OpenFileError) + } + defer func() { + if closeErr := f.Close(); closeErr != nil { + err = xerrors.Errorf("%+v: %w", closeErr, CloseFileError) + } + }() + + img, _, err := image.Decode(f) + if err != nil { + return xerrors.Errorf("%+v: %w", err, ReadImageError) + } + + newFilePath := fmt.Sprintf("%s.%s.%s", filePath, "converted", dest) + o, err := os.Create(newFilePath) + if err != nil { + return xerrors.Errorf("%+v: %w", err, CreateDestinationFileError) + } + defer func() { + if closeErr := o.Close(); closeErr != nil { + err = xerrors.Errorf("%+v: %w", closeErr, CloseFileError) + } + }() + + switch dest { + case "jpeg": + if err = jpeg.Encode(o, img, nil); err != nil { + return xerrors.Errorf("%+v: %w", err, EncodeImageError) + } + case "png": + if err = png.Encode(o, img); err != nil { + return xerrors.Errorf("%+v: %w", err, EncodeImageError) + } + } + return nil +} diff --git a/kadai2/tsuchinaga/imgconv/imgconv_test.go b/kadai2/tsuchinaga/imgconv/imgconv_test.go new file mode 100644 index 0000000..6e05bbc --- /dev/null +++ b/kadai2/tsuchinaga/imgconv/imgconv_test.go @@ -0,0 +1,272 @@ +package imgconv + +import ( + "errors" + "os" + "path/filepath" + "reflect" + "testing" +) + +func init() { + wd, err := os.Getwd() + if err != nil { + panic(err) + } + if "imgconv" == filepath.Base(wd) { + if err := os.Chdir(".."); err != nil { + panic(err) + } + } +} + +func TestConverter_IsDir(t *testing.T) { + t.Parallel() + testTable := []struct { + desc string + arg string + expect1 bool + expect2 error + }{ + {desc: "ディレクトリを指定したらtrue", arg: "./testdata", expect1: true}, + {desc: "ファイルを指定したらfalse", arg: "./testdata/Example.jpg", expect1: false}, + {desc: "存在しないパスを指定したらエラー", arg: "./NotFound.jpg", expect2: FileStatError}, + {desc: "空文字を指定したらエラー", arg: "", expect2: FileStatError}, + // {desc: "不良セクタを指定したらfalse", arg1: "", expect1: false}, // やり方わからない + } + + for _, test := range testTable { + test := test + t.Run(test.desc, func(t *testing.T) { + t.Parallel() + c := &converter{} + actual1, actual2 := c.IsDir(test.arg) + if test.expect1 != actual1 || !errors.Is(actual2, test.expect2) { + t.Errorf("%s 失敗\n期待: %v, %v\n実際: %v, %v\n", t.Name(), test.expect1, test.expect2, actual1, actual2) + } + }) + } +} + +func TestConverter_GetIMGType(t *testing.T) { + t.Parallel() + testTable := []struct { + desc string + arg string + expect1 string + expect2 error + }{ + {desc: "jpegファイルを指定したらjpegが返される", arg: "./testdata/Example.jpg", expect1: "jpeg"}, + {desc: "pngファイルを指定したらpngが返される", arg: "./testdata/Example.png", expect1: "png"}, + {desc: "テキストファイルを指定したらエラー", arg: "./testdata/Example.txt", expect2: NotImageError}, + {desc: "画像ではないバイナリファイルを指定したらエラー", arg: "./testdata/Example.xlsx", expect2: NotImageError}, + {desc: "存在しないパスを指定したらエラー", arg: "./foo/bar", expect2: OpenFileError}, + } + + for _, test := range testTable { + test := test + t.Run(test.desc, func(t *testing.T) { + t.Parallel() + c := &converter{} + actual1, actual2 := c.GetIMGType(test.arg) + if test.expect1 != actual1 || !errors.Is(actual2, test.expect2) { + t.Errorf("%s 失敗\n期待: %v, %v\n実際: %v, %v\n", t.Name(), test.expect1, test.expect2, actual1, actual2) + } + }) + } +} + +func TestConverter_DirFileList(t *testing.T) { + t.Parallel() + testTable := []struct { + desc string + arg string + expect1 []string + expect2 []string + expect3 error + }{ + {desc: "存在しないパスを指定したらエラー", arg: "", expect3: ReadDirError}, + {desc: "存在するパスを指定したら直下にあるディレクトリとファイルが返される", + arg: "./testdata", + expect1: []string{"testdata/subdir1", "testdata/subdir2"}, + expect2: []string{"testdata/Example.jpg", "testdata/Example.png", "testdata/Example.txt", "testdata/Example.xlsx"}}, + } + + for _, test := range testTable { + test := test + t.Run(test.desc, func(t *testing.T) { + t.Parallel() + c := &converter{} + actual1, actual2, actual3 := c.DirFileList(test.arg) + if !reflect.DeepEqual(test.expect1, actual1) || !reflect.DeepEqual(test.expect2, actual2) || !errors.Is(actual3, test.expect3) { + t.Errorf("%s 失敗\n期待: %+v, %+v, %+v\n実際: %+v, %+v, %+v\n", t.Name(), + test.expect1, test.expect2, test.expect3, actual1, actual2, actual3) + } + }) + } +} + +func TestConverter_Convert(t *testing.T) { + t.Parallel() + testTable := []struct { + desc string + arg1 string + arg2 string + arg3 string + expect error + }{ + {desc: "存在しないパスを指定したらエラー", arg1: "foo/bar", expect: OpenFileError}, + {desc: "画像じゃないファイルを指定したらエラー", arg1: "testdata/Example.txt", expect: NotImageError}, + {desc: "srcに指定した画像形式と違う画像形式なら何もせず終了", arg1: "testdata/Example.jpg", arg2: "png", expect: nil}, + // {desc: "Decodeできない画像ならエラー", arg1: "", expect: ReadImageError}, // 壊れた画像とか作ればいける? + // {desc: "空っぽの変換後のファイルを生成出来なかったらエラー", arg1: "", expect: CreateDestinationFileError}, // 吐き出し先にロックされたファイルを作ればいける? + // {desc: "jpgへの画像の変換に失敗したらエラー", arg1: "", expect: EncodeImageError}, // どうすれば失敗させられるのか分からない + // {desc: "pngへの画像の変換に失敗したらエラー", arg1: "", expect: EncodeImageError}, // どうすれば失敗させられるのか分からない + {desc: "正常に終了すればエラーなく終了", arg1: "testdata/subdir1/Example.jpg", arg2: "jpeg", arg3: "png", expect: nil}, + } + + for _, test := range testTable { + test := test + t.Run(test.desc, func(t *testing.T) { + t.Parallel() + c := &converter{} + actual := c.Convert(test.arg1, test.arg2, test.arg3) + if !errors.Is(actual, test.expect) { + t.Errorf("%s 失敗\n期待: %+v\n実際: %+v\n", t.Name(), test.expect, actual) + } + }) + } +} + +func TestNewConverter(t *testing.T) { + expect := &converter{} + actual := NewConverter() + if !reflect.DeepEqual(expect, actual) { + t.Errorf("%s 失敗\n期待: %+v\n実際: %+v\n", t.Name(), expect, actual) + } +} + +func TestNewIMGConverter(t *testing.T) { + expect := &imgConverter{converter: NewConverter()} + actual := NewIMGConverter() + if !reflect.DeepEqual(expect, actual) { + t.Errorf("%s 失敗\n期待: %+v\n実際: %+v\n", t.Name(), expect, actual) + } +} + +type testConverter struct { + dirFileListReturn map[int]struct { + ret1 []string + ret2 []string + ret3 error + } + dirFileListCount int + convertReturn map[int]error + convertCount int +} + +func (t testConverter) IsDir(string) (bool, error) { + panic("implement me") +} + +func (t testConverter) GetIMGType(string) (_ string, err error) { + panic("implement me") +} + +func (t *testConverter) DirFileList(string) ([]string, []string, error) { + rs := t.dirFileListReturn[t.dirFileListCount] + t.dirFileListCount++ + return rs.ret1, rs.ret2, rs.ret3 +} + +func (t *testConverter) Convert(string, string, string) (err error) { + r := t.convertReturn[t.convertCount] + t.convertCount++ + return r +} + +func TestImgConverter_Do(t *testing.T) { + t.Parallel() + testTable := []struct { + desc string + dirFileListReturn map[int]struct { + ret1 []string + ret2 []string + ret3 error + } + convertReturn map[int]error + expectDirFileListCount int + expectConvertCount int + expectErrorCount int + }{ + {desc: "dirが読み取れなければエラーを1回返して終わり", + dirFileListReturn: map[int]struct { + ret1 []string + ret2 []string + ret3 error + }{0: {ret3: ReadDirError}}, + expectDirFileListCount: 1, expectConvertCount: 0, expectErrorCount: 1, + }, + {desc: "dirが3段あれば3回実行する", + dirFileListReturn: map[int]struct { + ret1 []string + ret2 []string + ret3 error + }{0: {ret1: []string{"subdir1"}, ret2: []string{}}, + 1: {ret1: []string{"subdir2"}, ret2: []string{}}, + 2: {ret1: []string{}, ret2: []string{}}}, + expectDirFileListCount: 3, expectConvertCount: 0, expectErrorCount: 0, + }, + {desc: "fileの数だけconvertが叩かれる", + dirFileListReturn: map[int]struct { + ret1 []string + ret2 []string + ret3 error + }{0: {ret1: []string{}, ret2: []string{"file1", "file2", "file3", "file4"}}}, + expectDirFileListCount: 1, expectConvertCount: 4, expectErrorCount: 0, + }, + {desc: "fileの変換に失敗したらエラーが返される", + dirFileListReturn: map[int]struct { + ret1 []string + ret2 []string + ret3 error + }{0: {ret1: []string{}, ret2: []string{"file1", "file2", "file3", "file4"}}}, + convertReturn: map[int]error{0: ReadImageError, 2: ReadImageError}, + expectDirFileListCount: 1, expectConvertCount: 4, expectErrorCount: 2, + }, + {desc: "エラーなくdirもfileもなければ何もせずに抜ける", + dirFileListReturn: map[int]struct { + ret1 []string + ret2 []string + ret3 error + }{0: {ret1: []string{}, ret2: []string{}}}, + expectDirFileListCount: 1, expectConvertCount: 0, expectErrorCount: 0, + }, + } + + for _, test := range testTable { + test := test + t.Run(test.desc, func(t *testing.T) { + t.Parallel() + testConverter := &testConverter{ + dirFileListReturn: test.dirFileListReturn, + convertReturn: test.convertReturn, + } + imgConverter := &imgConverter{converter: testConverter} + + var errCount int + ch := imgConverter.Do("", "", "") + for range ch { + errCount++ + } + + if test.expectDirFileListCount != testConverter.dirFileListCount || + test.expectConvertCount != testConverter.convertCount || + test.expectErrorCount != errCount { + t.Errorf("%s 失敗\n期待: %d, %d, %d\n実際: %d, %d, %d\n", t.Name(), + test.expectDirFileListCount, test.expectConvertCount, test.expectErrorCount, + testConverter.dirFileListCount, testConverter.convertCount, errCount) + } + }) + } +} diff --git a/kadai2/tsuchinaga/main.go b/kadai2/tsuchinaga/main.go new file mode 100644 index 0000000..a055e27 --- /dev/null +++ b/kadai2/tsuchinaga/main.go @@ -0,0 +1,54 @@ +package main + +import ( + "flag" + "log" + "os" + + "github.com/gopherdojo/dojo8/kadai2/tsuchinaga/imgconv" + + "github.com/gopherdojo/dojo8/kadai2/tsuchinaga/validation" +) + +var ( + stderr Logger = log.New(os.Stderr, "", log.LstdFlags|log.Lmicroseconds) + validator = validation.NewValidator() + imgConverter = imgconv.NewIMGConverter() +) + +func main() { + // 入力値受け取り + var dir, src, dest string // ベースディレクトリ、変換元画像形式、変換後画像形式 + flag.StringVar(&dir, "dir", "", "変換する画像のあるディレクトリ") + flag.StringVar(&src, "src", "jpeg", "optional 変換元の画像形式 jpeg|png") + flag.StringVar(&dest, "dest", "png", "optional 変換後の画像形式 jpeg|png") + flag.Parse() + + // validatorで入力値チェック + switch { + case !validator.IsValidDir(dir): + stderr.Println("dirの指定は必須です") + os.Exit(2) + case !validator.IsValidSrc(src): + stderr.Println("srcに有効な画像形式を指定してください") + os.Exit(2) + case !validator.IsValidDest(dest, src): + stderr.Println("destに有効な画像形式を指定してください。また、srcとdestは一致しないよう指定してください") + os.Exit(2) + } + + // converterで変換の実行 + for err := range imgConverter.Do(dir, src, dest) { + switch err { + case imgconv.NotImageError: // 画像じゃないファイルも存在しうるので無視する + default: + stderr.Println(err) + } + + } +} + +// Logger - ログ出力のインターフェース +type Logger interface { + Println(v ...interface{}) +} diff --git a/kadai2/tsuchinaga/testdata/Example.jpg b/kadai2/tsuchinaga/testdata/Example.jpg new file mode 100644 index 0000000000000000000000000000000000000000..cacc09aa4804fcb30bae7ac36a2a59520e1d06e9 GIT binary patch literal 9022 zcmb7pWmp_dv-a+?xGnCwIDr5Gg6rb$?j!_v4el0Tk>Kv`o&*m8f=ke#!65_-1UsAO zIq!SEzhBLD^;Gv%&GbxF^;F;WwD`0EfGEl;$O3>sAix@N0G?I=(tmsZFM&XRdq^Mz zAt8amNC*OhQINr4WCV|lij0i%m%zxVsHiBYf7!n``QIBLw2)B1NZ`N2|9|w<55PkM zGy!Umfb;+m9uNr+_%sNh1^@wn=K%!#m(b8rP?0e}NZ`NMDG@IML`F3KM<_^$siA>@ zPs;!-gdPZj1OWhmAAS6_W&n~Fa+?)W&CC!ZVUiCUXCdzcLOB2=z) zU*&MPKUkcscuy&-6*UL;anV-?Xq_-__g|!lnG|Ay?yJ2Rr>_MYy8al{X_<~&WX*3N z^mv`lwYrb0J8f3&qA$||yqJ#G93CrFINpCX1vg}%?c4N)4R2ZW3vBaij--b`(pQ}iavF~<) zfq9j||8x;e5W>6+kiXUkAp!pD0mvv|R3M^{#w9_d4#6j+Lzo%uA144k1eDq)N`WSCViPd37r!U`5wCGi)>n-0K;p{;|6IZen%!YDnA=gSZ0ImZ>PQ_LT7WkJWo>K zC2>&w=%1Fud^`REU=n2q5$ICTH(4CZRt7qZlHAw23rVM=*Cu+O+8PRaP`5D}P%7G7 z>8?P_Y51;5&qRfxu#xw16=fQToTR^UBkE*xp&@=Ylv|f$(p$$A+ zSccbo!7DG9*2`6LITSqzHCRV>sj-QlRl}+=8VoK4IQfulV!l2BRuz?cU-rvpz03T;A0;dlFq# zl+QNN9Q`S&Zr}DDQWr6YX=^q40RB(X_rTWv&OJehsIKm>>R;3+m$8w16tTO5#(HVD zaidHGkKK8WyJTg&j>t~j1wV^X1P&xe zle#RRx~InV_w!bJjT}De4R2EP7O#9`+Fq&nM$Dh~1n@lrEkzXR1t*y=28uiK=tvLe z;H){U1ZDlu(pK@#5b)que`Md#@+Gn>Dt~{%+27evxvDb%s(0N~zdwK2U$bS4v{k24 zRmJwi$nMrtvUb2>Jz=g|8HtOmj<3G1uxzBR;Xcz0d0FjP9O28tcmN;>jD!qEMMnSE z$AO4N3>gIvK*x=WFR5WcKuga9<&x5L4S_=lU$`|A5ldSZ_HAyR{o~?DK%hAADw}61 z^bk3E|JNIhg5OVoZ}n6t?4$U4R9KxK!Xui{*QElI`B*7C6UY;B@~s`PtUDh^E(zJ8 zR`0vK3(V|@xp6pvwhG{qeLw$SG&(9aE!|oeK8dgZsP06sZ=eYuIVE{1UMp0ooO4cD zooOqN`3G%2EQ3)o26FQma6&15S8ke9r@QBLq%*HM_wFAF6di5W5a13 zIeH#n_10I7h2|j!YGt%O6k>-#sc%1h`Bv_iTUk!n;_Qs_aYiPQUML}lyLnM1yHm)L zHEPvO@a?dtF?Pb$akl%!&9Vdaq{+J&x~s>j9(tLRA5*xe+_-pT&*GKdB}YM=aKb6& z4>Ph(&?2G%ylbh41iL}Ptfn;HjD+vp5A2FD=s3X}Q4k^+5cL?q9qbdMbd+Hy$Ab?NPp_uT^g+U-f7G4UO8eBf ze0|`EWUbus?_6A1>B7ru=|D|5?fxjyKHHDx%!SPD)Gmf!Sp=6 zSI;cJ$qda^n+=aZ9}fhRW{q^BT;0anI-JpT_tDJgCi<7$K4lmZ&-~V@7<$nHo;0G4 zYsmmWmU&jsll0!2(0}*%i8oei(A>-vq78%gZOn%)w1?QFD?gf*`;qfA5wS^WOOYf8 z^M5D#m_U2@d(WleJXYt^7_DxTIF{>8p568Uh5q|S@k}YDg4yNaJD9$Yw+OQ`&Zkd>6-Tw5KI~a>( z_01vN0?)ZGChb`}M1GDIPmi6%t-aOOZVhND8?^gvV0GhIk-d^R`b{*bj7f9x0A^RX zrO~zJi8|M|Db;0ZB@kKj1H=H>>GAN2QB~t<@ZZkuxFjK&Itg`W%9)Givcp7^K$edA zdi1&XPuX|heER4czn_RW=0U_U5)udr6@-lZe{l>z#-rm#L@@y&Ej<^Hh14d5=!NSv zys_`>*FWKl$f*$F`8P!GRL{H41TeH^U5xpjRdE+*)*n6-`> zT36kTb|{sMWL0Xg+7&tdgDU;5mX+hfcbtN`4EeU?mQxP}aTVz&{0yB1gu}kfBu5d1Rg`nk-FBKCgcPh0R=Q?+ z@T-;&b3$K`Z>ryEMHBP7lKwqkw@kO84pzHcV|8QIR9e{!!)QSaj( zVY@lmzT>m7Oe_i2Xca`}UMSzqxumlDd|1@fZaiIQW~Z2$JRw`jJKl-?^*PJV`OPJ# z%7C$@DYb@D(1jo?<~iS3si7H5Cu>>S`%kuUA8ZNU5X(aD+6-}D^OU;t&encf)Wnf1lC^zL;v5ua<6ihjTSzBTB>ESwZJFwK zxS~!^EyAdh5QI@dNXSU&i0l^WuUSDr#NvzxK*1-V3#W-0d12~((wqO<7zjWS2R#82^{3}MePfN3cGc@onJ4yO_fG)YvCP)%l^TJd zAFX^a06gga)l`?~ukGJ_F?fdQ89!R@7=%x4#iRGU_oB+@7=-x?1&_KeNJJKz5|oRhRp zIyJ?3^DXo(k_m8~z%+a#AHjM2MongHxp={e8 zvjf;&+Eq!(--)!j88*zBCtokQ_jLD+h^0a7@Xyy&2h?6C%@-eQrQ~7;UYUwfq})r= zy)U;>Y;>>`Dz2cfD!cQsSZ|5n)^HPLB8&){qzY2(*x>kColL(~EEU$4$i&Sy8!LzI zh>K4hxBB5z+jXrT&t>$Sk7l0cS8j!8*yZ^DOg)zy=N%1?@16GkK5)0+4XbuNme&sI z-p|4HomtVGwh(TBry)W>gexC^pc5N^B128-gdMB@R1Hdb~&Wac9&v zwkD!sHbb$>xa2*Ea0BnBNCa%h&>F)YO<|09niTttDhKiF@a7YPo4L%x%hgJaWMSDE z)#?~J@1iRFKx0>QYZZa3oDfcKtz8VeW!SfBsdDX^HnW)?5ROS2OVM0fF>~H@i=$wy zk=ysXM*ON1ejV0V?Ui(2wHNZomYcIHQI3Dg^e;`86d6a9=$I4-`218AD49P}yRGp> zbI!MFfmwHH5abw)trco&peJ;gTT$t%;4Sp#;xuB`g;ac*+q`kZoobD0rNdOGr=w`0zZ$cNG- ziPAZBBN3Di*?dZNlBbCO!jMVkQgEfGPgej9A@6nlF9V;_lL4Z{=BuxShYy^}^tQrA z0l_p3w~FgHmya26CjKegam^gX7=O&SZ`3F@ii>NjH&{wWX>17wzGzpC!HVLlo|WlN zH0^z5j}5>l>)M8pN|4Zq!c2~0Q+TDy=9?*5Mz^&ID$sBM9dNr7IEt`1YgKgXm$qE(r1m7uNeaNU>rf1$teSY~RR~<{iVVjCq+=gAo#3 zo(q<%FF2V^g!?)T8NZk}txjL@`3{%)+DNX2YOK|foWA$RSiO?)fX*aeF}t}~ce`&< z-k;A{W&WQ3?AvL_t+7mRU+?MZjdYrXLm%o zC&BtOa4cL4hsx4Ox6XEts25J^8Ce!mNt#(WY}=2>VT5AOH`hA9ftNd^A-#_4)V#-g z$KwbNt*cvfWIHxoD3!lxzA}_)bLe6AUGk~vkL&s4d6Z;4 z>rsci90$H?`6A;stFxkCO%_JTZX77=`3-$NA8#gms58Fu>}XhsVeVq_&p4_Ta@;T< z_4}yXa|-T{>@KXOTscRl^Zv0+G?rNUqX-a^oYqTBqSY(l6BAa8t2x?2$(at)Q`Y)4 z@n+6uV>%CTX{Djn$VU)kw*#F`C;Aaaf@Zx?#lo)jK6e!mgb`%slv!=nobajfkTmM} zi0KLNK{e*aZ%bBfqzPgSUec+?OLsRhu<5CE+sM9oNiO_)jW0!}a`L$c(%lw{X;ItP z(V90WZG()QV=B0l-#akkK}#cc1L~pnE3YQt#=c?y5Gh+>G}P@h&}n^y=Eq@tl`WaCx>(h6bq>O3+{uU|>y07ilU}eT zHu7yh8Pq;`TmG;a+bxf+fV89yMGrigdoUx>fvG+LI@(fi>N+(l3$YBW*Q@M5J-F1! zpdRWdl*!(ewKuubn<~WK`KA~f;6uC!P=vC|;#Qw!#6t{Sv-nui=^O+0&^~T!|LEi9 zsnjy#dtJ?E=18L=WPsOJUq>~z^yq=@M+uH`ZY)TifpJ-h?CVJ~yFddwg&jm487OMALv$4=(W`!gbpU_lB_ zS@(qxm9GK~9~9*Jt<@xvM>Fu<6jc z@f*kQ)wpVo{<$w+ix{~@5s@!eYF3-$mzTm2fuTluexvsHd}-GRo3`fWrzcR%<&0U{ z90T8LUl@iv&f1<5|N5y~`CG7dHq$l&EuqFM6O8w*)bYWUI6-e{iu`9>ORj_E~YEn8vlk=3z6{-TFK5XyfcLLeebmjq~7K)56j+w4O1 z#_7$oU$p35LR&7!<{er3gP%gcD zfZT!%lmJQ&Xt5o9Svznh{3e`3d5NVf{RD7LBW9Prz1xc_Ye>LfXk>5iJ3gd0&`Y}> z0+9d?{PX|?RwcyP`f}{Jg7+~d;s#1o=;$Juy@fQz^$s$Q*!(#>Z$oAyustu*m3tLp zcc`%kvAj9?#ry$eohYAIw0LR+LHN6LO>W@F#WI2Sqn3 za9FUGhsNSC#yZrp8XBs$l4B|mU=mjQ;l7N3^pj=0=QNLV-5rlGF&Vt#B6w|;R$Dzt z_v*bEU*lY0OOiw=^PfeGm0=l+++PvA^dxDGQAfR=q-p6~N5%@1Ua!ZHbs{py@RjN^ zsI7lXRcD;B?1XA zk^RlgjZ3JvVd3sWOejxVVNSB8!aF$~RH(bAx+*lpqkX)RUsa2nbR7j--zee>sXw_7 ziloHJwJmEM19C<&OLrg^L~?TR!>smDJKm@tPbwZ}o6<{aOIGW69%g8H^x)zb@IhOb z!AHuk_j_Zbif~(h=)?Q+2I;L{+vsLvTBeaHmVzjc+37Ph6ve1=mYFU#Y)e8i5^i)d zHY}!sqy`>NQ*yB`HiMV&q#nU*k3IRO(ft;(&4N%h%?@6U4IJUml7bSEw4SC+Nq~No z_pjB~weDRip3(5n z{77cI6pwiz*Tj@&!S4Hxib-+|+Edr`#LE-OR;!G(>JD5|Ixvl_>)^)qB$=XVl_2a! z61=h2N{U{60xTx3j;4mre`JQWg#?L^Fq{Zle?~!`up@l};G)_0A!-5)nHWHEGqb1$ z7dHT2y`1?uA(ZZ$a~wkyh5#x36QFQ=StnpjsFcA(m7~OJFhf@And2k@g9N*v(SV;UL)Pc@bVm3@f?ws^5Y=`;ZPu@D0W|V0atjs8ZHayfLKXmN*(oD; z(T<${tbRPQ6wZzuKe-Z{xbLjAQDzlS0K^*hPq_o|clU~@c>FIJb0M?*WhpSi5ak{K z04(!?HT>CMM)gJ<_n#5(xfuJu3}E?PL+{@+`0R}K?-|JOdhj0x0C2(jJAj~#f7-td zVtr-6LzI0G4@B&h{{w~K(E+$6xin}kTpJ;91bX>j>=JTIVQ;@Rxp8+NO8uUHiC$~f zCEaWac4yo|Zc&{FcphOEp9tiD^({lkJr?gL+h-D)CJrT>Pk! zo80QlBbQXQyYQRT49PT-qF+bINi1yX7h;Mbv0|faa~VIi--1J{*7#-66PQWSm+^W@ z!AW@P9J3*5!3A#~5*aA`(tAOdMWY=8`e^ENE%Ytu2Bf6MGE(ufjD+6PYF}&$=#)ne zR3j4}WAPsfUdljW@V=Mvloo6tyTZ^SE+fG&g}5d1`JKc3>J;qVArzE^iVFiG5Sf=8 zJ(|Z_=Y*0#6uZ~-nxlqpxyhDX9%2~{QrV_N0Cy>M6?6ThsT?;vdJ$t|xl>d@6})JU zJ@thCgorx1s-G?QpHGp4QLsEpNsqUQc(l*h=*2LmRw5*nzesDOMRznK3)pbWUaCC6 zEP1VZJ%kpz<-E{2hzB+Z?iQ`#wgan8G3jLoO%xDF2`x6JQ$!o^mCL*Ykv89p#9L%i zB&XS>ewKR>t53K_5mWR9C9IhmJ?W1c#D+|}7d87D-kqEh8LDWPD=BwKL%T)ka7=SR z04uUR3w?`L9*+R5#MgHFi7Vp!L*YjNQ%nJ|(y(hlkH^K9=NouQ`K+**Gr}Dh@esv0 zFbD`nVAcP+3Ggqtts!aQN*e-iY!7#{ue4eh^uHSYR)*N<7Z};r+y7&&e z!}It*dGs&>W)I7@A1(FgH*OlJ5Qeo^ANZl$NGh%L^AqqR-9|+ zj}LkbC@P6+YtjrcI|_Ku4yR%7%K8%B9#jOl)Xy2|?ZrSVBx`-HPJ5*gGYcG@Zu(eD zC%;-tksK!SaCP|WmmgN}c4H5JksTAzZM50;#lSn2!Yv7q#}mEm2)wZRb5xlt^Yab+ zo^cH=j6z7@nCOX&kEayR!MX8{**`tdxn@LubnP%O5xd2#TXO1+Iym?A^r#m&F=Tk@ z>RqC)Y#b%LHE1Ps7H2o=u|o#>$0+gLn(zO~eOq6r`|a)ZMJ)WRvKJULxOJ~0AWfP& zC^J#E_ILoRAtoUlc>=iHtJMNWzf7ZW$rKO#{`7{Nr%Wza@aA3V6j#i&Z&>}B8eV@O zgs@b3gfr~9h}QraS}2?ZIo|d8)*$o6-x?Yd$tq<3}8O2=$YBaWvRW#v;dd-N-MVOK~R}XC18Rd#wx)lSu_9u;D4f1 zrK3v>lQ&1&PAd3VT=IcH?g4)x)*ol596LQu=c-p;>&LQp#H(=bwM&;XF1go+HK5)p zXfR-|irYtQki$L@kjnN4+^Sx2SY&9OErH_iY1?oK3+c;n+0Ei>Z!r@OKD~+1<^@L8 z6i;si@`P=m8Y4(5&` z-{+ny&3E7~PMBlxLTk}p#PZI~#{tV&XM}`n7lwG1&0$o%6HsW%!OGyNVp_CH@qZ&S zxBH4)`!-bM<#?jJ2Lm01`>-Q#zP8*}HFA@8#70_XuJcVt`8B<&t8RtAwpvBTZ&;hm z6hBOw(rpOG1ud0LQc^#+0r^dqG)yU>A=`2Qyu$%53@@3B1@eY;Dc{D$+R~L75yF?i z)}ikeYg}XwS_#mhrSDnx3u`|_(mflhn(Box*%lcSuStXh*uK5h$`32jpp8n?EYkNI zi2^Z_ld$!LaOnu3e`0cci}XT^Cy$-5fe=-*cTf)_I*qV`CDTIfeJ%6}@T;I=k&Kjh zNL1{_YRg zvkea9M=hEVzCVoWE#Yvv{_RN5Ayp0ACB$>@Oy%N7 zHbCVM^fQpmSy3TbM-u7xBnNW#Q{Xr7k;_>{qO-U#j2mZ}(&T|~?E3}?9fqqFwO1tU zH1$8bpft&)C5RyfxwM`L7ewu$(*$P(LoKDG3wZp5jGWp5?h=SE4hvSoCAY+QBzg?;{tJ3R;kJqw0%gV(#`IF$wh9P%Ls^qlc%odN2jc ziv>rN;Yk&!6C!Jy7D(|JM)KRM~p#TXBEx56bY;Do2iuW=nRp za*)ThezOY(qGK-Oc@Quz%B+M9=aij7z%N~u<-#}wbqqT&h=A&gmf_Deq%M@Pe}`M^*dg&s zy|(8>W_%2mp<-d4m14L8r7)V~i<$RGg>ROugz73W`Ip=h?7hZ#|CUP!NCzCJuJa%@>lvgzW$SnOi5xXtuTQ zbVj0_xJ^HOT{=Py<6n`#7kgk2?14S72ll`o*aLfD5A1Sx9O@S><0@o{QNkk^VV;HbPw(U)R{`f|$#>k{;n$m=F~3|wMov?JE9)o7*+d_#4NujV|T1YQB;?waY-yek$+{{(g=4!hqCOel_$v!wdYwf-;d zjB@|06()jpUo0o~TCI^pJ7YPhW-*gmlQdcQ)^5+V zd7imw9V?&}>S;=UhQQb?hMloG8L6pWN}-FjcD?<&{X(z-d~Me}jxk5X?+DY`7u0NL z26bPo1u1%g^kTJXDf8`mgA@7r^ViRXW?onsF=AFV5rJ6vECJSiv9O}g%PV?OC3xG- z#}#AH=Bv$BG$*wzlqX>Ynv^F6b!V*PteT+w6VvizLAmoYt$_xqQL06w6%`^fx9*LV zFi6Vk*e~2m0j)GurfOxbWHT)|HTz*!NV4w!FCyn5Bq~gF`5LuL(MsA%;{v1M(0OYfP1>D&<;O$%efDlY;aCfmH6i<=8_K zQFH4Bt7#eQtVJ5J6_cV`a3#fh>bqkl4k3ovPxs}%ZIAm26(c#uB*w&4*s7V=32l|a zOkC*^1=gLh$sbbu*{VOBx;(b~_CWmiJ{}oR)rE_il8=ZeXJZ*`{|83&+T$>U^mv?3 zrxjnA@AqZ7KYAbfIAD!=%ry~|r7)?i%wyDXcWj2!D@?rH9r+Zmj$TnVK10ZZgTpxB zlar{j#u&KojrCg=0&tfTsQ2yuHb2(B_TLG;J3I|O-8o+5eglV2wBdo4)UjO!u!QRQ7~{y*^;|qJ3=`jTKe|(tvjD+g~4nj6Bxh;`KSX zxG}u5oz@q17=~!!quzB%>S1;MiacavO&!kQN!rJc!uH^x?Xf~Uj6Tq>2>>|qC%^eN z$xtE#5@qb4jD6|UvWpWgJ{SAdO#NSW&1lDU6bPcbl>7-*CFSA%|7Wh&KuUzMa_wj| z*Sq*3*mQMsz&$8w=Kps9vS1hNf?co+cEK*#1-oDu?1Eje3wFUS*af>_7wm$Stv?@@ zU?~Cs+yPd_kYu$EYZ6_yd=5)Wl1P?P1RDIed#hFhlgCBN=ddzz0Vd(W4h{Otmd{}c zSR@IEb#47R(pGX^wtNnoB_MJKmhZkO@GLB?CpB{S{ji2ludFP*0hY9#Oat&WQ3X)7p`OX*T^OQ6OM$lCqGwP*gD_p^ zU=7VFYvnJ103*!x#uB7S7~iw7h0}HgI0Gi%rtpWBZSM(^;8&rp!G4*t377N$9Qiv- zpN6;b?RoIM3Tt=^cES-*@6Q0omJYR*P)@>hU4mu2{h9^rhTI-o=9JA#i;w^>!OkNq zX_t|P<#=m(L_xrVFuuG7>!d8Q9Bq4|g!#+ZvBhwvL+=3@VOP+)1WUkMmZhP{bt#}a z0fPhVvBl3;7QmtiyRWP(X+RMvOWAh6tqo^Q>uU-F`r4b;F01Bt(>E)?L&OuX z*`uL;TN{reTeVMBD!`h(;a)>F05-kLV^<|*6Y(6Zte#0S0T+6LZJK>qy-PTG(*jJ( zK(X9H$`By|V3#K1IasDF$y(J=Z3b3!jkZFdfU~zB1&~<)n|*G*vk+iXHWAOjLa8F| z5wld8&@KX4qB-ye+h;NKl(TeLRB0lffi;HT&w8!=#cD9y`k^;_S`uJ7D{Qq55zoL9 zdaa^-T`;7@Oi)MOt}*7$o<+bA@f56(%4R4z!n$Q$o_*{cWcN;HiiU@X=TB=AnE>Z3 zFwDQlQ}jdchMf6w5CcxcbFg_Ui9DYYWZd@HASZ7D9eEQl{x(;pz(hO`O9L#b8%w97 z2H2eQnmuV}Z@1oduOxVR+BRW`Nc}#nTESO-MixL?TVP#^Y-Tg}?46YD_flZ>%rBXV zn5B3RO8_v19DX$ja7$wEm&&695IFYkpLUZvyOaSt5p#s|7PfoupUP?5G})bo6;2JG zlXrGmjt4VHom-J&Iv;-vTlnaO;atbhy%jWjZ(ko>dLz?2k3fF&mu~{UsWkMnMUF6- zCn}&n0vlRGCtktN!4|`YPt?JG61Gs{ZxuA|QkWy)at~Mv0ASq$wq5H#lRv)}?1Eje z3wFUS*af>_7wkXn-N66=004u)k>roLM;b+t!KJcVvjG8K5d=x8K^VFvN9hgK)O@u9J;#^kPxH?Ct13q9U_r1CSBF|KIvAegma(L#o~U1W)0LKV;W< z-Yrx~-FvX--%r%UPG`EJWIn~``EBA>f*4*Y^?}qzq|$u!n~Q`{=J3O>B(|Z2ttB(b zQF=(_=gQ4>=2_wO$1$YIxtbFm7^L&aRkNq(FREtHJN&C?bxMI8;+TGJ7&?q_B$^E2 zCk827B6W-duQ?0};5p*~g{?rCM#^j4hZ!wWOuDS3Q0low(J<3!($VIQOl<*5|M6Ot zHLcQ&tEU`rRMiww^vAS^@9p>n6t~oF(RWXt6bh?zv2O_GyIT(i&rlrgtsW0uvqx`%@}wDu8CAgg5#A;!E=n%-DjbS^)2xw=KEv3) zx{Z&>pu0O10O&6;tkvdcIz`-3L7)s90YeiA*v^HI_viJ0@cS>u+@Jn>Y3wt#ZhoBL z1H~U91MsPZXaX6ayR>36gO<-*rEmDPkvYuN3+-$)1X@%9C&|| zu99GsSC+-REbbYlKCu4JgF%I-u8 z>41y*%h~cb19l8&msHxCR-)Dw=9v&NMo$wGdi3jHkE zXTAnC!bd|Ho;@O%-6aEugZ|-kg^LJA`a4Kab?NogPym1_3;^IKj6Cf4+#Mmd=8lfG zKY6ND+t@K(jKI5H;|^sd!}J6ftB5RdDsoasJvE;%rksYq6U)>_~0k)q3WbBm|>0?HG*x$6?oM!dvQ z57ZWKTw2yw&QnheQ2I>GGt*r|H znYss_ZA3(ePMaP!y4pTj(6Rs+Ckbu$3&67&dlHXsMsP8#spm_l$saXCcm|?wD`e|+MFcd zK^yxL`*pt-9)79Zp}bBf5|;;R_ZD=VUlC}_;s$Q<%LXSuVG|r9<0lZJR<4$? zNmG>QXp9ppxhw+5mKUMzQ|W!5sqwHxK5y5DVPXZLT_Ky8F@t5w`-K>(Er{%GHU_7X z2*0(@K?*}k9xR>ngdjJ+{-|x&FmaBy~4?7yRX}g>CqGyYJ>ibfI!pXPk79e_| zvQN(x4Yx6=C?GiAYRA}xAqNfALkdE99EpR!+61|9aXXPP1RfJ?E_GrPGPAJ7*`4d_ zBo}R8w)1;4H~0Fh3s&wN{lJi#lmtdf;)d@vA8Vae1Lf;ibM8-0%y@&nd+Up~oA5$A z8ce>v4=`<<`U)+L#bw7rWAG3^xB<>SLx~r7Z!|KeKB;lSpm*s^@RG|m=#8Z(5~S?W zfVk~yL+_`k7JAp{d`rpYTthaeFV*9=jlMd2B(hOD)mVJr!sRj;RJqFRygbX8?J2D++#kBFepn`MAq$J=cvP(u7Z)^}15bqiEgaUXK~wmRPs zKu@}s#ACJhrycDiW6GBDZ>o>y=F=`BfT>-wT&TdI?hY&H_aF#NlnPU zp6|<6v*j}+yuua-|Cyj7L*|@d2+Z*y2#N}D4+(+2e{s~G5%@b_AtBmD1cLv&S82?U z&2Q~e&}~4nx5O)~y!e6Hc$vE18vsKTT~A`*i`cKeCd>W{Qi=~}@0Fu3xG>whORi?C zk~G3qWnT<@NHc%Rct>4f@=295q^xanhHVmGSN8CNm7XPkwZ6Nz?dNjM3gZX&RVM(|(&)qSK zNwo2;RHC&aIVd5FCoH%X8Wn=Y!D&CxVN zxGC2<9fWLy-$u13Of7d>2qU;|9iZXd2nPX64?M!1*Gq(a{&$io7>UfGq*vT5^Lp zk*5;DVI=jl>9O~vr-)t;Arz{rwYheB~JWnXwE}y>m)~>Fhp|`5C zYQbDxy*YnOH-oaeqTEz=$E#w%kL@UE1bfVRot)}qM!HtPce zt{tC=Lw%(2yHK!l;{z8vYfdvi*{MvAD?gF18uA>+TfBS%hUsPC-+kNt1(mY z>e~v{sGX4Kah05%Yb%#CncTOW_*+N@tRv2)9c#o6$=Y1zmG>0!N0P;JdNR>sDW(^3 zkSOChS6kJS3cE#-c0-u^;%p<1lISO$Gg_u35i$NdLl>g3P#GZD`4j!m)8ubi;A#c7 z2lM@Q{Vf4@^$o+RMM!-3P9t$zQZyye3Bm(QY#e-PPfx@a)cCgp%M{A z?h%dj+}4-tTr5l7gQ1a1g7%m2-~gF!c%a-Mg?b_^vAv_Kz3%4RP7#Z9M_9fk&N|wCJ)toAs(4Z}ieOjiuW3zIB$CN7}6L5AS zA|I7zahK!mPMZn(djSSsc_t`@M*U~sZw%V& zCJKh|N$o63XKvM6RmBbs9mocfNncWFlFw#AmEvckoBcLu+oFvXX=_0JV zDYmht8ijE(`QVxrG?kvY=#|wlLN=k5TOK-)mkNT_om$D>omv>K3caQ34zZoR3 z)Ca^Calo&2>F$m$uNNJcyf3fg)Fz5XSA)WQZ%0B#eXrJ`lilxJG{vt^w@(hTo?P$d zn6&$>j4f_#bp+xoMFhEHXL-2m<6yfU_GA2*Vh$!`OhkPrRWIviB2RYs6d z`Ia?G-%6D9$sv#@)tz0LIdugUsCLu$p8r+pJ`zKsF?=9YsFQWVOR5ErQ8f-{(2rEH zaSSi4lMkC*+NltaT}t4?ZC+9$LK-1pszSAADQR8HUlZdQ_D=I&hVw*Fn(kC~nL?6X_@*Qkd3KF*8{7=u%}@fe|3;Lo&eE$>rW>BwFE zE4YSgJng{K57|C%Z4DRbSRI(FjAK$+>@IlqcV>6LNE~sQ5MdnPd^|&{ClXCtvLo7w z?A27RuNKoRr^nD7RbYpb)!N(GQ!S+waltxL-|<~%tBYe(C9i&aYXEhT5riz$@+cBw z_!f_;;X18mF)Z5cRng1k_tR+gKj4C1IOprjCHuhWPAE4@*iD|jklbV{J$^ESKXP}1 zgLDtXm-pjmZJvkjpPubLOKV2LVk%h-Q#$Ti*)*CZz7+yTHNS0q>)&5?aS$(-rt#@> zBl1h)eM!Bqr(@!c0n5z#qxwnOBVg^-yMvO{XI__8iH)UTUR%oP`DyAR@bNJkXIjfp zj@Of;zQoZ$P!k_H$pO~F8R4P4(EW~V2Zim-wPLhK;V|2;rd3Xw?`tCZQ{E&ESV_tV zS>YzQp}24gPH8TWB)@$hbN}m})*IFO{l_D#5)V}$XRKH4*yOX4C~mCgIX%EL=1lo$ zd)DGruK~UOpt%4xCIVGKWxA4wS=HU53;8fQv3;M)KzC*IglV~{ly4@qfqdmENRv9x z{d67hpHCY4P~_5DTJ=eLKGE?}P8$RsaBdnE7Kl*Br4j;I&IOSnY9gf5kwcm#K-oPO zar+qlt`SzVKr>XnE`8Tj9(eevn~;0aQ?(THMrsJvSzp>=tuo^#1m)SViZt;-?)r2w z!?)6ivC?(5YzrKdRmz_CAV=d+)#V*9vuD$?30w7WL$n0*$4QvjcJ3@aE0If7Y{PoV zI`pF-t5}GY!#Wmopf67&Yi@!swWw3mo~3vSEJk?2A%Y!P5EZ@r#c275c6j>}J*6tq z1}{mfEDsFV&j*b6Dl4Arpwkc|kz=e+rdlA2n3c#S_AfOCZ~&V(wBz4@aHSd753C~Y zRoUP$VjCx=y{W14JBlx(#A$Nq3MdjYy*n?uUdb`g|E!pLnPLqlb+c)T+fIADhO2YQ zU{k5AS?^Oo=2>pb>q3iKd=l@`S#(W=;V;dTHT*H30$N~}P+hH_Hit%r8q8uty;~>7 zl%D9Z5J$K6S)ojfKG7`??~S*;!=g=ffUM$ui3Z7ZO^zC_<{k=i1H$$lWS;ER zRD^AwE~*B%UU?O?u3TpIAe+D&84#{=ko-(J*_@dk54;;vG+iX_AMjM(SyTnOi{TU` zO+MS(df%kEB`T?2SXZ8#SI}G3WU}XM-Mew6sfDgM&2xz<+I6u+8-2v4T9Zq-WKWu5 z%Z)1NMg3QfQ=5g?j$_}0BR60%2eh_MW96>`4BFKT6Pg!fKwKPGkuN^n*W%pEUUWDO zIL|4K@JlGzW~xR@);*cKMKJB(sW^E-Ams$ntTQ3#824XP?Ba^31};Cluo~?Vn|UdM zHu5XHp+(Z09*8{?$D}i=9~qX?hw0jys-)ehS>pl-kZbru=h&#kiV+z01;X2@`@iQ;c#i_B{6^`2`aPVx3s5--%4Z za&|APduDJ8UILYQkndS*wA8$MaOADYT|~bjRaS_qmRCbhR`+^2Eg?Twcs~~ALxL)6 zLcr=A&QI98^!DCIzOP(Rkoi;YG@;MC`JG*gBynGYv{HvfL1o=Y93Waew?La#>UVGPlccE1InSr??_J>7Ahsrl`0jG*ZLWPD(U3l5a=0G40>CB((qtNb*{z)l~!SG z4afVpg0qgFKxv>bQ9pXI?FFP+okM_;$&>zq1&xc-5Y*% zkWl!*67w`R&tL=gbm8hvwZDO))peps!>z~b4}+``D~o9Dn8_?Ic|eaBkDb%;$~b_J z%DC5{v*z1vI%P2T^3ouk;n>)ipxD6XxjhG0Y{i1?^sL5$i}I!rV_n7ar@Xt?DdrxN z9 z7LGJ(FQ1D)%KZG|@=>V&s#9seluZeynHt2`|yVTsB|wsy5K!jx3$$Uus?*=-C&Po z$55Ji=9U%Hw;-_n&V9(|AEhK&+pryV#2sq{LI@GZSxZL?5X8~Rh0nqf0{)2*gzEag zQ!Juv#K!^=qCd&gO~qY?V{zvvp=$BDMA`2P1LX)qQ^4(Ygq0Sv!8I1ab{~igO+#nY zn(@-rWV2N$=HP9sURmi8i7if<(%UU099ZIXqV!gS5COIEJ=fh#Mg?j{3Jzr?4g){= zoZUnE4}$r5{$KeiN_ zd)Mk!bh4l8BUsH2RyDMEx$M|{IxC#D3PB^6RjtnbG~$`?tpIo?EA(EODD>Q z=jPHiDKp-q5Yx>PlSS_ZNE#InO|nHmuYF_&gxuIjwVxgPX3YJDSR^!GnuPAsnL=W6 z^e!11P)FW^eZ;pi`?dka5_9pIW)^X3{)Z~PIO`pifyhHj#Ic#+&v|I(U;f|K33Q6?)(kASnS#h@WeU@~Hh*OvIJ1vPFMwsys zLYHB@0ubWnMsOQ(>P1q#NM|#a&6xo!YuXuQGeq$-Pk&e2Xu>wQf6!laI>6lS4Lut0QbA>0tx z2wTAlRAX^H=s@7+J8_{(WrT3E1eUiFDPkkx5@1V!W2vQujQm#kFIE{ zW7xK!CX)A@k)%6s$5$H-DM;d-xg$!a!l=aWf7w^r82zQq&;Lu`XHx*U-Ef0!_XfPZ!H*J;@AhClZZ1Wx`m8~fGp*9pNNrlsir(WHK#7yN4cSBdiv zQviS+>o?>7NAUdB&#zM0AD$F({__xj6UKh^@~f2chZj}6e-u`Jb?|Eg_=kg8(%&5X z(GLD<`d4=R!w>*~BecE0apkY(e=TZ%Hut6elli|(90-Vphz$UMiTFH0(6Pq-pWpru Dt^2RD literal 0 HcmV?d00001 diff --git a/kadai2/tsuchinaga/testdata/subdir1/Example.jpg b/kadai2/tsuchinaga/testdata/subdir1/Example.jpg new file mode 100644 index 0000000000000000000000000000000000000000..cacc09aa4804fcb30bae7ac36a2a59520e1d06e9 GIT binary patch literal 9022 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