blob: 56927a58296a4ab92db05d2ad0920eb23d249112 [file] [log] [blame]
// Licensed to the Apache Software Foundation (ASF) under one or more
// contributor license agreements. See the NOTICE file distributed with
// this work for additional information regarding copyright ownership.
// The ASF licenses this file to You under the Apache License, Version 2.0
// (the "License"); you may not use this file except in compliance with
// the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package bufmodulebuild
import (
"context"
"io"
"path/filepath"
"strings"
"testing"
"github.com/apache/dubbo-kubernetes/pkg/bufman/bufpkg/bufcheck/bufbreaking/bufbreakingconfig"
"github.com/apache/dubbo-kubernetes/pkg/bufman/bufpkg/bufcheck/buflint/buflintconfig"
"github.com/apache/dubbo-kubernetes/pkg/bufman/bufpkg/bufmodule"
"github.com/apache/dubbo-kubernetes/pkg/bufman/bufpkg/bufmodule/bufmoduleconfig"
"github.com/apache/dubbo-kubernetes/pkg/bufman/bufpkg/bufmodule/bufmoduleref"
"github.com/apache/dubbo-kubernetes/pkg/bufman/bufpkg/bufmodule/bufmoduletesting"
"github.com/apache/dubbo-kubernetes/pkg/bufman/pkg/normalpath"
"github.com/apache/dubbo-kubernetes/pkg/bufman/pkg/storage"
"github.com/apache/dubbo-kubernetes/pkg/bufman/pkg/storage/storagemem"
"github.com/apache/dubbo-kubernetes/pkg/bufman/pkg/storage/storageos"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestBucketGetFileInfos1(t *testing.T) {
t.Parallel()
config, err := bufmoduleconfig.NewConfigV1(
bufmoduleconfig.ExternalConfigV1{
Excludes: []string{"proto/b"},
},
)
require.NoError(t, err)
testBucketGetFileInfos(
t,
"testdata/1",
config,
bufmoduletesting.NewFileInfo(t, "proto/a/1.proto", "testdata/1/proto/a/1.proto", false, nil, ""),
bufmoduletesting.NewFileInfo(t, "proto/a/2.proto", "testdata/1/proto/a/2.proto", false, nil, ""),
bufmoduletesting.NewFileInfo(t, "proto/a/3.proto", "testdata/1/proto/a/3.proto", false, nil, ""),
bufmoduletesting.NewFileInfo(t, "proto/a/c/1.proto", "testdata/1/proto/a/c/1.proto", false, nil, ""),
bufmoduletesting.NewFileInfo(t, "proto/a/c/2.proto", "testdata/1/proto/a/c/2.proto", false, nil, ""),
bufmoduletesting.NewFileInfo(t, "proto/a/c/3.proto", "testdata/1/proto/a/c/3.proto", false, nil, ""),
bufmoduletesting.NewFileInfo(t, "proto/d/1.proto", "testdata/1/proto/d/1.proto", false, nil, ""),
bufmoduletesting.NewFileInfo(t, "proto/d/2.proto", "testdata/1/proto/d/2.proto", false, nil, ""),
bufmoduletesting.NewFileInfo(t, "proto/d/3.proto", "testdata/1/proto/d/3.proto", false, nil, ""),
)
}
func TestBucketGetFileInfos2(t *testing.T) {
t.Parallel()
config, err := bufmoduleconfig.NewConfigV1(
bufmoduleconfig.ExternalConfigV1{
Excludes: []string{"proto/a"},
},
)
require.NoError(t, err)
testBucketGetFileInfos(
t,
"testdata/1",
config,
bufmoduletesting.NewFileInfo(t, "proto/b/1.proto", "testdata/1/proto/b/1.proto", false, nil, ""),
bufmoduletesting.NewFileInfo(t, "proto/b/2.proto", "testdata/1/proto/b/2.proto", false, nil, ""),
bufmoduletesting.NewFileInfo(t, "proto/b/3.proto", "testdata/1/proto/b/3.proto", false, nil, ""),
bufmoduletesting.NewFileInfo(t, "proto/d/1.proto", "testdata/1/proto/d/1.proto", false, nil, ""),
bufmoduletesting.NewFileInfo(t, "proto/d/2.proto", "testdata/1/proto/d/2.proto", false, nil, ""),
bufmoduletesting.NewFileInfo(t, "proto/d/3.proto", "testdata/1/proto/d/3.proto", false, nil, ""),
)
}
func TestBucketGetFileInfo3(t *testing.T) {
t.Parallel()
config, err := bufmoduleconfig.NewConfigV1(
bufmoduleconfig.ExternalConfigV1{
Excludes: []string{"proto/a/c"},
},
)
require.NoError(t, err)
testBucketGetFileInfos(
t,
"testdata/1",
config,
bufmoduletesting.NewFileInfo(t, "proto/a/1.proto", "testdata/1/proto/a/1.proto", false, nil, ""),
bufmoduletesting.NewFileInfo(t, "proto/a/2.proto", "testdata/1/proto/a/2.proto", false, nil, ""),
bufmoduletesting.NewFileInfo(t, "proto/a/3.proto", "testdata/1/proto/a/3.proto", false, nil, ""),
bufmoduletesting.NewFileInfo(t, "proto/b/1.proto", "testdata/1/proto/b/1.proto", false, nil, ""),
bufmoduletesting.NewFileInfo(t, "proto/b/2.proto", "testdata/1/proto/b/2.proto", false, nil, ""),
bufmoduletesting.NewFileInfo(t, "proto/b/3.proto", "testdata/1/proto/b/3.proto", false, nil, ""),
bufmoduletesting.NewFileInfo(t, "proto/d/1.proto", "testdata/1/proto/d/1.proto", false, nil, ""),
bufmoduletesting.NewFileInfo(t, "proto/d/2.proto", "testdata/1/proto/d/2.proto", false, nil, ""),
bufmoduletesting.NewFileInfo(t, "proto/d/3.proto", "testdata/1/proto/d/3.proto", false, nil, ""),
)
}
func TestBucketGetFileInfos4(t *testing.T) {
t.Parallel()
config, err := bufmoduleconfig.NewConfigV1(
bufmoduleconfig.ExternalConfigV1{
Excludes: []string{
"proto/a/c",
"proto/d",
},
},
)
require.NoError(t, err)
testBucketGetFileInfos(
t,
"testdata/1",
config,
bufmoduletesting.NewFileInfo(t, "proto/a/1.proto", "testdata/1/proto/a/1.proto", false, nil, ""),
bufmoduletesting.NewFileInfo(t, "proto/a/2.proto", "testdata/1/proto/a/2.proto", false, nil, ""),
bufmoduletesting.NewFileInfo(t, "proto/a/3.proto", "testdata/1/proto/a/3.proto", false, nil, ""),
bufmoduletesting.NewFileInfo(t, "proto/b/1.proto", "testdata/1/proto/b/1.proto", false, nil, ""),
bufmoduletesting.NewFileInfo(t, "proto/b/2.proto", "testdata/1/proto/b/2.proto", false, nil, ""),
bufmoduletesting.NewFileInfo(t, "proto/b/3.proto", "testdata/1/proto/b/3.proto", false, nil, ""),
)
}
func TestBucketGetAllFileInfos5(t *testing.T) {
t.Parallel()
config, err := bufmoduleconfig.NewConfigV1(
bufmoduleconfig.ExternalConfigV1{},
)
require.NoError(t, err)
testBucketGetFileInfos(
t,
"testdata/3",
config,
)
}
func TestConfigV1Beta1BucketGetFileInfos1(t *testing.T) {
t.Parallel()
config, err := bufmoduleconfig.NewConfigV1Beta1(
bufmoduleconfig.ExternalConfigV1Beta1{
Roots: []string{
"proto",
},
Excludes: []string{
"proto/b",
},
},
)
require.NoError(t, err)
testBucketGetFileInfos(
t,
"testdata/1",
config,
bufmoduletesting.NewFileInfo(t, "a/1.proto", "testdata/1/proto/a/1.proto", false, nil, ""),
bufmoduletesting.NewFileInfo(t, "a/2.proto", "testdata/1/proto/a/2.proto", false, nil, ""),
bufmoduletesting.NewFileInfo(t, "a/3.proto", "testdata/1/proto/a/3.proto", false, nil, ""),
bufmoduletesting.NewFileInfo(t, "a/c/1.proto", "testdata/1/proto/a/c/1.proto", false, nil, ""),
bufmoduletesting.NewFileInfo(t, "a/c/2.proto", "testdata/1/proto/a/c/2.proto", false, nil, ""),
bufmoduletesting.NewFileInfo(t, "a/c/3.proto", "testdata/1/proto/a/c/3.proto", false, nil, ""),
bufmoduletesting.NewFileInfo(t, "d/1.proto", "testdata/1/proto/d/1.proto", false, nil, ""),
bufmoduletesting.NewFileInfo(t, "d/2.proto", "testdata/1/proto/d/2.proto", false, nil, ""),
bufmoduletesting.NewFileInfo(t, "d/3.proto", "testdata/1/proto/d/3.proto", false, nil, ""),
)
}
func TestConfigV1Beta1BucketGetFileInfos2(t *testing.T) {
t.Parallel()
config, err := bufmoduleconfig.NewConfigV1Beta1(
bufmoduleconfig.ExternalConfigV1Beta1{
Roots: []string{
"proto",
},
Excludes: []string{
"proto/a",
},
},
)
require.NoError(t, err)
testBucketGetFileInfos(
t,
"testdata/1",
config,
bufmoduletesting.NewFileInfo(t, "b/1.proto", "testdata/1/proto/b/1.proto", false, nil, ""),
bufmoduletesting.NewFileInfo(t, "b/2.proto", "testdata/1/proto/b/2.proto", false, nil, ""),
bufmoduletesting.NewFileInfo(t, "b/3.proto", "testdata/1/proto/b/3.proto", false, nil, ""),
bufmoduletesting.NewFileInfo(t, "d/1.proto", "testdata/1/proto/d/1.proto", false, nil, ""),
bufmoduletesting.NewFileInfo(t, "d/2.proto", "testdata/1/proto/d/2.proto", false, nil, ""),
bufmoduletesting.NewFileInfo(t, "d/3.proto", "testdata/1/proto/d/3.proto", false, nil, ""),
)
}
func TestConfigV1Beta1BucketGetFileInfo3(t *testing.T) {
t.Parallel()
config, err := bufmoduleconfig.NewConfigV1Beta1(
bufmoduleconfig.ExternalConfigV1Beta1{
Roots: []string{
"proto",
},
Excludes: []string{
"proto/a/c",
},
},
)
require.NoError(t, err)
testBucketGetFileInfos(
t,
"testdata/1",
config,
bufmoduletesting.NewFileInfo(t, "a/1.proto", "testdata/1/proto/a/1.proto", false, nil, ""),
bufmoduletesting.NewFileInfo(t, "a/2.proto", "testdata/1/proto/a/2.proto", false, nil, ""),
bufmoduletesting.NewFileInfo(t, "a/3.proto", "testdata/1/proto/a/3.proto", false, nil, ""),
bufmoduletesting.NewFileInfo(t, "b/1.proto", "testdata/1/proto/b/1.proto", false, nil, ""),
bufmoduletesting.NewFileInfo(t, "b/2.proto", "testdata/1/proto/b/2.proto", false, nil, ""),
bufmoduletesting.NewFileInfo(t, "b/3.proto", "testdata/1/proto/b/3.proto", false, nil, ""),
bufmoduletesting.NewFileInfo(t, "d/1.proto", "testdata/1/proto/d/1.proto", false, nil, ""),
bufmoduletesting.NewFileInfo(t, "d/2.proto", "testdata/1/proto/d/2.proto", false, nil, ""),
bufmoduletesting.NewFileInfo(t, "d/3.proto", "testdata/1/proto/d/3.proto", false, nil, ""),
)
}
func TestConfigV1Beta1BucketGetFileInfos4(t *testing.T) {
t.Parallel()
config, err := bufmoduleconfig.NewConfigV1Beta1(
bufmoduleconfig.ExternalConfigV1Beta1{
Roots: []string{
"proto",
},
Excludes: []string{
"proto/a/c",
"proto/d",
},
},
)
require.NoError(t, err)
testBucketGetFileInfos(
t,
"testdata/1",
config,
bufmoduletesting.NewFileInfo(t, "a/1.proto", "testdata/1/proto/a/1.proto", false, nil, ""),
bufmoduletesting.NewFileInfo(t, "a/2.proto", "testdata/1/proto/a/2.proto", false, nil, ""),
bufmoduletesting.NewFileInfo(t, "a/3.proto", "testdata/1/proto/a/3.proto", false, nil, ""),
bufmoduletesting.NewFileInfo(t, "b/1.proto", "testdata/1/proto/b/1.proto", false, nil, ""),
bufmoduletesting.NewFileInfo(t, "b/2.proto", "testdata/1/proto/b/2.proto", false, nil, ""),
bufmoduletesting.NewFileInfo(t, "b/3.proto", "testdata/1/proto/b/3.proto", false, nil, ""),
)
}
func TestConfigV1Beta1BucketGetAllFileInfos5(t *testing.T) {
t.Parallel()
config, err := bufmoduleconfig.NewConfigV1Beta1(
bufmoduleconfig.ExternalConfigV1Beta1{
Roots: []string{
".",
},
},
)
require.NoError(t, err)
testBucketGetFileInfos(
t,
"testdata/3",
config,
)
}
func TestConfigV1Beta1BucketGetAllFileInfosError1(t *testing.T) {
t.Parallel()
config, err := bufmoduleconfig.NewConfigV1Beta1(
bufmoduleconfig.ExternalConfigV1Beta1{
Roots: []string{
"a",
"b",
},
},
)
require.NoError(t, err)
testBucketGetAllFileInfosError(
t,
"testdata/2",
config,
nil,
)
}
func TestConfigV1Beta1BucketGetFileInfosForExternalPathsError1(t *testing.T) {
t.Parallel()
config, err := bufmoduleconfig.NewConfigV1Beta1(
bufmoduleconfig.ExternalConfigV1Beta1{
Roots: []string{
"a",
"b",
},
},
)
require.NoError(t, err)
testBucketGetFileInfosForExternalPathsError(
t,
"testdata/2",
config,
[]string{
"testdata/2/a/1.proto",
"testdata/2/a/2.proto",
"testdata/2/a/3.proto",
"testdata/2/b/1.proto",
"testdata/2/b/4.proto",
},
)
}
func TestDocumentation(t *testing.T) {
t.Parallel()
testDocumentationBucket(
t,
"testdata/4",
bufmodule.DefaultDocumentationPath,
bufmoduletesting.NewFileInfo(t, "proto/1.proto", "testdata/4/proto/1.proto", false, nil, ""),
bufmoduletesting.NewFileInfo(t, "proto/a/2.proto", "testdata/4/proto/a/2.proto", false, nil, ""),
)
}
func TestLicense(t *testing.T) {
t.Parallel()
testLicenseBucket(
t,
"testdata/5",
"Test Module License",
bufmoduletesting.NewFileInfo(t, "proto/1.proto", "testdata/5/proto/1.proto", false, nil, ""),
bufmoduletesting.NewFileInfo(t, "proto/a/2.proto", "testdata/5/proto/a/2.proto", false, nil, ""),
)
}
func TestConfigInclusion(t *testing.T) {
t.Parallel()
t.Run("buf.yaml", func(t *testing.T) {
t.Parallel()
testConfigInclusion(t, "buf.yaml")
})
t.Run("buf.mod", func(t *testing.T) {
t.Parallel()
testConfigInclusion(t, "buf.mod")
})
}
func testConfigInclusion(t *testing.T, confname string) {
// bucket creation
bufyaml := `
version: v1
breaking:
ignore_unstable_packages: true
lint:
allow_comment_ignores: true
`
ctx := context.Background()
bucket, err := memBucket(ctx,
confname, bufyaml,
"a/1.proto", "",
)
require.NoError(t, err)
// build
config, err := bufmoduleconfig.NewConfigV1(
bufmoduleconfig.ExternalConfigV1{},
)
require.NoError(t, err)
module, err := NewModuleBucketBuilder().BuildForBucket(
ctx,
bucket,
config,
)
require.NoError(t, err)
require.NotNil(t, module)
// assert: one proto consumed
fileInfos, err := module.TargetFileInfos(ctx)
assert.NoError(t, err)
assert.Len(t, fileInfos, 1)
// assert: breaking and lint configuration exists
zeroBreaking := bufbreakingconfig.NewConfigV1(
bufbreakingconfig.ExternalConfigV1{},
)
assert.NotEqual(t, zeroBreaking, module.BreakingConfig(), "empty BreakingConfig")
zeroLint := buflintconfig.NewConfigV1(
buflintconfig.ExternalConfigV1{},
)
assert.NotEqual(t, zeroLint, module.LintConfig(), "empty LintConfig")
}
func memBucket(ctx context.Context, pathcontent ...string) (storage.ReadBucket, error) {
membucket := storagemem.NewReadWriteBucket()
for i := 0; i < len(pathcontent); i += 2 {
fh, err := membucket.Put(ctx, pathcontent[i])
if err != nil {
return nil, err
}
_, err = io.Copy(fh, strings.NewReader(pathcontent[i+1]))
if err != nil {
return nil, err
}
fh.Close()
}
return membucket, nil
}
func testBucketGetFileInfos(
t *testing.T,
relDir string,
config *bufmoduleconfig.Config,
expectedFileInfos ...bufmoduleref.FileInfo,
) {
storageosProvider := storageos.NewProvider(storageos.ProviderWithSymlinks())
readWriteBucket, err := storageosProvider.NewReadWriteBucket(
relDir,
storageos.ReadWriteBucketWithSymlinksIfSupported(),
)
require.NoError(t, err)
module, err := NewModuleBucketBuilder().BuildForBucket(
context.Background(),
readWriteBucket,
config,
)
require.NoError(t, err)
fileInfos, err := module.SourceFileInfos(context.Background())
assert.NoError(t, err)
assert.Equal(
t,
expectedFileInfos,
fileInfos,
)
if len(expectedFileInfos) > 1 {
expectedFileInfos = expectedFileInfos[:len(expectedFileInfos)-1]
bucketRelPaths := make([]string, len(expectedFileInfos))
for i, expectedFileInfo := range expectedFileInfos {
bucketRelExternalPath, err := filepath.Rel(relDir, expectedFileInfo.ExternalPath())
require.NoError(t, err)
bucketRelPath, err := normalpath.NormalizeAndValidate(bucketRelExternalPath)
require.NoError(t, err)
bucketRelPaths[i] = bucketRelPath
}
module, err := NewModuleBucketBuilder().BuildForBucket(
context.Background(),
readWriteBucket,
config,
WithPaths(bucketRelPaths),
)
require.NoError(t, err)
fileInfos, err := module.TargetFileInfos(context.Background())
assert.NoError(t, err)
assert.Equal(
t,
expectedFileInfos,
fileInfos,
)
}
}
func testBucketGetAllFileInfosError(
t *testing.T,
relDir string,
config *bufmoduleconfig.Config,
expectedSpecificError error,
) {
storageosProvider := storageos.NewProvider(storageos.ProviderWithSymlinks())
readWriteBucket, err := storageosProvider.NewReadWriteBucket(
relDir,
storageos.ReadWriteBucketWithSymlinksIfSupported(),
)
require.NoError(t, err)
module, err := NewModuleBucketBuilder().BuildForBucket(
context.Background(),
readWriteBucket,
config,
)
require.NoError(t, err)
_, err = module.SourceFileInfos(context.Background())
if expectedSpecificError != nil {
assert.Equal(t, expectedSpecificError, err)
} else {
assert.Error(t, err)
}
}
func testBucketGetFileInfosForExternalPathsError(
t *testing.T,
relDir string,
config *bufmoduleconfig.Config,
externalPaths []string,
) {
storageosProvider := storageos.NewProvider(storageos.ProviderWithSymlinks())
readWriteBucket, err := storageosProvider.NewReadWriteBucket(
relDir,
storageos.ReadWriteBucketWithSymlinksIfSupported(),
)
require.NoError(t, err)
bucketRelPaths := make([]string, len(externalPaths))
for i, externalPath := range externalPaths {
bucketRelExternalPath, err := filepath.Rel(relDir, externalPath)
require.NoError(t, err)
bucketRelPath, err := normalpath.NormalizeAndValidate(bucketRelExternalPath)
require.NoError(t, err)
bucketRelPaths[i] = bucketRelPath
}
_, err = NewModuleBucketBuilder().BuildForBucket(
context.Background(),
readWriteBucket,
config,
WithPaths(bucketRelPaths),
)
assert.Error(t, err)
}
func testDocumentationBucket(
t *testing.T,
relDir string,
expectedDocPath string,
expectedFileInfos ...bufmoduleref.FileInfo,
) {
storageosProvider := storageos.NewProvider(storageos.ProviderWithSymlinks())
readWriteBucket, err := storageosProvider.NewReadWriteBucket(
relDir,
storageos.ReadWriteBucketWithSymlinksIfSupported(),
)
require.NoError(t, err)
config, err := bufmoduleconfig.NewConfigV1(
bufmoduleconfig.ExternalConfigV1{},
)
require.NoError(t, err)
module, err := NewModuleBucketBuilder().BuildForBucket(
context.Background(),
readWriteBucket,
config,
)
require.NoError(t, err)
require.NotNil(t, module)
assert.NotEmpty(t, module.Documentation())
assert.Equal(t, expectedDocPath, module.DocumentationPath())
fileInfos, err := module.TargetFileInfos(context.Background())
assert.NoError(t, err)
assert.Equal(
t,
expectedFileInfos,
fileInfos,
)
}
func testLicenseBucket(
t *testing.T,
relDir string,
expectedLicense string,
expectedFileInfos ...bufmoduleref.FileInfo,
) {
storageosProvider := storageos.NewProvider(storageos.ProviderWithSymlinks())
readWriteBucket, err := storageosProvider.NewReadWriteBucket(
relDir,
storageos.ReadWriteBucketWithSymlinksIfSupported(),
)
require.NoError(t, err)
config, err := bufmoduleconfig.NewConfigV1(
bufmoduleconfig.ExternalConfigV1{},
)
require.NoError(t, err)
module, err := NewModuleBucketBuilder().BuildForBucket(
context.Background(),
readWriteBucket,
config,
)
require.NoError(t, err)
require.NotNil(t, module)
assert.NotEmpty(t, module.License())
assert.Equal(t, expectedLicense, module.License())
fileInfos, err := module.TargetFileInfos(context.Background())
assert.NoError(t, err)
assert.Equal(
t,
expectedFileInfos,
fileInfos,
)
}