From 3853d83d737efe0b6b9d8cfceefdc5fdd8ba3753 Mon Sep 17 00:00:00 2001 From: Stavros Panakakis <53979866+Stavrospanakakis@users.noreply.github.com> Date: Fri, 20 Sep 2024 15:36:12 +0300 Subject: [PATCH] go : add tests and update bindings (#2425) Update Go version to ^1.23, the actions/setup-go to v5, actions/checkout to v4 and github.com/stretchr/testify to v1.9.0. Add test cases for the following model struct methods: - New - Close - NewContext - IsMultilingual - Languages Add test cases for the following context struct methods: - SetLanguage - IsMultilingual - Language - Process --- .github/workflows/bindings-go.yml | 6 +- bindings/go/go.mod | 4 +- bindings/go/go.sum | 11 +-- bindings/go/pkg/whisper/context_test.go | 110 ++++++++++++++++-------- bindings/go/pkg/whisper/model_test.go | 91 ++++++++++++++++++++ bindings/go/pkg/whisper/util_test.go | 6 ++ 6 files changed, 178 insertions(+), 50 deletions(-) create mode 100644 bindings/go/pkg/whisper/model_test.go create mode 100644 bindings/go/pkg/whisper/util_test.go diff --git a/.github/workflows/bindings-go.yml b/.github/workflows/bindings-go.yml index 13f1950a..9808cf0f 100644 --- a/.github/workflows/bindings-go.yml +++ b/.github/workflows/bindings-go.yml @@ -13,10 +13,10 @@ jobs: ubuntu-latest: runs-on: ubuntu-latest steps: - - uses: actions/setup-go@v3 + - uses: actions/setup-go@v5 with: - go-version: '^1.19' - - uses: actions/checkout@v1 + go-version: '^1.23' + - uses: actions/checkout@v4 - run: | cd bindings/go make test diff --git a/bindings/go/go.mod b/bindings/go/go.mod index 594f184b..7c92c7b4 100644 --- a/bindings/go/go.mod +++ b/bindings/go/go.mod @@ -1,10 +1,10 @@ module github.com/ggerganov/whisper.cpp/bindings/go -go 1.19 +go 1.23 require ( github.com/go-audio/wav v1.1.0 - github.com/stretchr/testify v1.8.1 + github.com/stretchr/testify v1.9.0 ) require ( diff --git a/bindings/go/go.sum b/bindings/go/go.sum index 870ebdc3..1f99aebd 100644 --- a/bindings/go/go.sum +++ b/bindings/go/go.sum @@ -1,4 +1,3 @@ -github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/go-audio/audio v1.0.0 h1:zS9vebldgbQqktK4H0lUqWrG8P0NxCJVqcj7ZpNnwd4= @@ -9,15 +8,9 @@ github.com/go-audio/wav v1.1.0 h1:jQgLtbqBzY7G+BM8fXF7AHUk1uHUviWS4X39d5rsL2g= github.com/go-audio/wav v1.1.0/go.mod h1:mpe9qfwbScEbkd8uybLuIpTgHyrISw/OTuvjUW2iGtE= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= -github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= -github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= -github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/bindings/go/pkg/whisper/context_test.go b/bindings/go/pkg/whisper/context_test.go index c8c6016e..7d83a8df 100644 --- a/bindings/go/pkg/whisper/context_test.go +++ b/bindings/go/pkg/whisper/context_test.go @@ -4,52 +4,90 @@ import ( "os" "testing" - // Packages - whisper "github.com/ggerganov/whisper.cpp/bindings/go/pkg/whisper" + "github.com/ggerganov/whisper.cpp/bindings/go/pkg/whisper" + "github.com/go-audio/wav" assert "github.com/stretchr/testify/assert" ) -const ( - ModelPath = "../../models/ggml-tiny.bin" - SamplePath = "../../samples/jfk.wav" -) - -func Test_Whisper_000(t *testing.T) { +func TestSetLanguage(t *testing.T) { assert := assert.New(t) - if _, err := os.Stat(ModelPath); os.IsNotExist(err) { - t.Skip("Skipping test, model not found:", ModelPath) - } - if _, err := os.Stat(SamplePath); os.IsNotExist(err) { - t.Skip("Skipping test, sample not found:", SamplePath) - } - // Load model - model, err := whisper.New(ModelPath) - assert.NoError(err) - assert.NotNil(model) - assert.NoError(model.Close()) - - t.Log("languages=", model.Languages()) -} - -func Test_Whisper_001(t *testing.T) { - assert := assert.New(t) - if _, err := os.Stat(ModelPath); os.IsNotExist(err) { - t.Skip("Skipping test, model not found:", ModelPath) - } - if _, err := os.Stat(SamplePath); os.IsNotExist(err) { - t.Skip("Skipping test, sample not found:", SamplePath) - } - - // Load model model, err := whisper.New(ModelPath) assert.NoError(err) assert.NotNil(model) defer model.Close() - // Get context for decoding - ctx, err := model.NewContext() + context, err := model.NewContext() assert.NoError(err) - assert.NotNil(ctx) + // This returns an error since + // the model 'models/ggml-small.en.bin' + // that is loaded is not multilingual + err = context.SetLanguage("en") + assert.Error(err) +} + +func TestContextModelIsMultilingual(t *testing.T) { + assert := assert.New(t) + + model, err := whisper.New(ModelPath) + assert.NoError(err) + assert.NotNil(model) + defer model.Close() + + context, err := model.NewContext() + assert.NoError(err) + + isMultilingual := context.IsMultilingual() + + // This returns false since + // the model 'models/ggml-small.en.bin' + // that is loaded is not multilingual + assert.False(isMultilingual) +} + +func TestLanguage(t *testing.T) { + assert := assert.New(t) + + model, err := whisper.New(ModelPath) + assert.NoError(err) + assert.NotNil(model) + defer model.Close() + + context, err := model.NewContext() + assert.NoError(err) + + // This always returns en since + // the model 'models/ggml-small.en.bin' + // that is loaded is not multilingual + expectedLanguage := "en" + actualLanguage := context.Language() + assert.Equal(expectedLanguage, actualLanguage) +} + +func TestProcess(t *testing.T) { + assert := assert.New(t) + + fh, err := os.Open(SamplePath) + assert.NoError(err) + defer fh.Close() + + // Decode the WAV file - load the full buffer + dec := wav.NewDecoder(fh) + buf, err := dec.FullPCMBuffer() + assert.NoError(err) + assert.Equal(uint16(1), dec.NumChans) + + data := buf.AsFloat32Buffer().Data + + model, err := whisper.New(ModelPath) + assert.NoError(err) + assert.NotNil(model) + defer model.Close() + + context, err := model.NewContext() + assert.NoError(err) + + err = context.Process(data, nil, nil) + assert.NoError(err) } diff --git a/bindings/go/pkg/whisper/model_test.go b/bindings/go/pkg/whisper/model_test.go new file mode 100644 index 00000000..8797f0d0 --- /dev/null +++ b/bindings/go/pkg/whisper/model_test.go @@ -0,0 +1,91 @@ +package whisper_test + +import ( + "testing" + + "github.com/ggerganov/whisper.cpp/bindings/go/pkg/whisper" + assert "github.com/stretchr/testify/assert" +) + +func TestNew(t *testing.T) { + assert := assert.New(t) + t.Run("valid model path", func(t *testing.T) { + model, err := whisper.New(ModelPath) + assert.NoError(err) + assert.NotNil(model) + defer model.Close() + + }) + + t.Run("invalid model path", func(t *testing.T) { + invalidModelPath := "invalid-model-path.bin" + model, err := whisper.New(invalidModelPath) + assert.Error(err) + assert.Nil(model) + }) +} + +func TestClose(t *testing.T) { + assert := assert.New(t) + + model, err := whisper.New(ModelPath) + assert.NoError(err) + assert.NotNil(model) + + err = model.Close() + assert.NoError(err) +} + +func TestNewContext(t *testing.T) { + assert := assert.New(t) + + model, err := whisper.New(ModelPath) + assert.NoError(err) + assert.NotNil(model) + defer model.Close() + + context, err := model.NewContext() + assert.NoError(err) + assert.NotNil(context) +} + +func TestIsMultilingual(t *testing.T) { + assert := assert.New(t) + + model, err := whisper.New(ModelPath) + assert.NoError(err) + assert.NotNil(model) + defer model.Close() + + isMultilingual := model.IsMultilingual() + + // This returns false since + // the model 'models/ggml-small.en.bin' + // that is loaded is not multilingual + assert.False(isMultilingual) +} + +func TestLanguages(t *testing.T) { + assert := assert.New(t) + + model, err := whisper.New(ModelPath) + assert.NoError(err) + assert.NotNil(model) + defer model.Close() + + expectedLanguages := []string{ + "en", "zh", "de", "es", "ru", "ko", "fr", "ja", "pt", "tr", "pl", + "ca", "nl", "ar", "sv", "it", "id", "hi", "fi", "vi", "he", "uk", + "el", "ms", "cs", "ro", "da", "hu", "ta", "no", "th", "ur", "hr", + "bg", "lt", "la", "mi", "ml", "cy", "sk", "te", "fa", "lv", "bn", + "sr", "az", "sl", "kn", "et", "mk", "br", "eu", "is", "hy", "ne", + "mn", "bs", "kk", "sq", "sw", "gl", "mr", "pa", "si", "km", "sn", + "yo", "so", "af", "oc", "ka", "be", "tg", "sd", "gu", "am", "yi", + "lo", "uz", "fo", "ht", "ps", "tk", "nn", "mt", "sa", "lb", "my", + "bo", "tl", "mg", "as", "tt", "haw", "ln", "ha", "ba", "jw", "su", + } + + actualLanguages := model.Languages() + + assert.Equal(expectedLanguages, actualLanguages) +} diff --git a/bindings/go/pkg/whisper/util_test.go b/bindings/go/pkg/whisper/util_test.go new file mode 100644 index 00000000..8ea2d5b4 --- /dev/null +++ b/bindings/go/pkg/whisper/util_test.go @@ -0,0 +1,6 @@ +package whisper_test + +const ( + ModelPath = "../../models/ggml-small.en.bin" + SamplePath = "../../samples/jfk.wav" +)