github.com/pingcap/tiflow@v0.0.0-20240520035814-5bf52d54e205/pkg/sink/cloudstorage/config_test.go (about)

     1  // Copyright 2022 PingCAP, Inc.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // See the License for the specific language governing permissions and
    12  // limitations under the License.
    13  
    14  package cloudstorage
    15  
    16  import (
    17  	"context"
    18  	"net/url"
    19  	"testing"
    20  	"time"
    21  
    22  	"github.com/aws/aws-sdk-go/aws"
    23  	"github.com/pingcap/tiflow/pkg/config"
    24  	"github.com/stretchr/testify/require"
    25  )
    26  
    27  func TestConfigApply(t *testing.T) {
    28  	expected := NewConfig()
    29  	expected.WorkerCount = 32
    30  	expected.FlushInterval = 10 * time.Second
    31  	expected.FileSize = 16 * 1024 * 1024
    32  	expected.FileIndexWidth = config.DefaultFileIndexWidth
    33  	expected.DateSeparator = config.DateSeparatorDay.String()
    34  	expected.EnablePartitionSeparator = true
    35  	expected.FlushConcurrency = 1
    36  	uri := "s3://bucket/prefix?worker-count=32&flush-interval=10s&file-size=16777216&protocol=csv"
    37  	sinkURI, err := url.Parse(uri)
    38  	require.Nil(t, err)
    39  
    40  	replicaConfig := config.GetDefaultReplicaConfig()
    41  	err = replicaConfig.ValidateAndAdjust(sinkURI)
    42  	require.NoError(t, err)
    43  	cfg := NewConfig()
    44  	err = cfg.Apply(context.TODO(), sinkURI, replicaConfig)
    45  	require.Nil(t, err)
    46  	require.Equal(t, expected, cfg)
    47  }
    48  
    49  func TestVerifySinkURIParams(t *testing.T) {
    50  	testCases := []struct {
    51  		name        string
    52  		uri         string
    53  		expectedErr string
    54  	}{
    55  		{
    56  			name:        "valid sink uri with local/nfs scheme",
    57  			uri:         "file://tmp/test",
    58  			expectedErr: "",
    59  		},
    60  		{
    61  			name:        "valid sink uri with s3 scheme",
    62  			uri:         "s3://bucket/prefix",
    63  			expectedErr: "",
    64  		},
    65  		{
    66  			name:        "valid sink uri with gcs scheme",
    67  			uri:         "gcs://bucket/prefix",
    68  			expectedErr: "",
    69  		},
    70  		{
    71  			name:        "valid sink uri with azblob scheme",
    72  			uri:         "azblob://bucket/prefix",
    73  			expectedErr: "",
    74  		},
    75  		{
    76  			name:        "sink uri with valid scheme, worker-count, flush-interval and file-size",
    77  			uri:         "s3://bucket/prefix?worker-count=64&flush-interval=1m30s&file-size=33554432",
    78  			expectedErr: "",
    79  		},
    80  		{
    81  			name:        "invalid sink uri with unknown storage scheme",
    82  			uri:         "xxx://tmp/test",
    83  			expectedErr: "can't create cloud storage sink with unsupported scheme",
    84  		},
    85  		{
    86  			name:        "invalid sink uri with worker-count number less than lower limit",
    87  			uri:         "file://tmp/test?worker-count=-1",
    88  			expectedErr: "invalid worker-count -1, it must be greater than 0",
    89  		},
    90  		{
    91  			name:        "invalid sink uri with worker-count number greater than upper limit",
    92  			uri:         "s3://bucket/prefix?worker-count=10000",
    93  			expectedErr: "",
    94  		},
    95  		{
    96  			name:        "invalid sink uri with flush-interval less than lower limit",
    97  			uri:         "s3://bucket/prefix?flush-interval=-10s",
    98  			expectedErr: "",
    99  		},
   100  		{
   101  			name:        "invalid sink uri with flush-interval greater than upper limit",
   102  			uri:         "s3://bucket/prefix?flush=interval=1h",
   103  			expectedErr: "",
   104  		},
   105  		{
   106  			name:        "invalid sink uri with file-size less than lower limit",
   107  			uri:         "s3://bucket/prefix?file-size=1024",
   108  			expectedErr: "",
   109  		},
   110  		{
   111  			name:        "invalid sink uri with file-size greater than upper limit",
   112  			uri:         "s3://bucket/prefix?file-size=1073741824",
   113  			expectedErr: "",
   114  		},
   115  	}
   116  
   117  	for _, tc := range testCases {
   118  		sinkURI, err := url.Parse(tc.uri)
   119  		require.Nil(t, err)
   120  		cfg := NewConfig()
   121  		err = cfg.Apply(context.TODO(), sinkURI, config.GetDefaultReplicaConfig())
   122  		if tc.expectedErr == "" {
   123  			require.Nil(t, err)
   124  			require.LessOrEqual(t, cfg.WorkerCount, maxWorkerCount)
   125  			require.LessOrEqual(t, cfg.FlushInterval, maxFlushInterval)
   126  			require.LessOrEqual(t, cfg.FileSize, maxFileSize)
   127  		} else {
   128  			require.Regexp(t, tc.expectedErr, err)
   129  		}
   130  	}
   131  }
   132  
   133  func TestMergeConfig(t *testing.T) {
   134  	uri := "s3://bucket/prefix"
   135  	sinkURI, err := url.Parse(uri)
   136  	require.NoError(t, err)
   137  	replicaConfig := config.GetDefaultReplicaConfig()
   138  	replicaConfig.Sink.CloudStorageConfig = &config.CloudStorageConfig{
   139  		WorkerCount:    aws.Int(12),
   140  		FileSize:       aws.Int(1485760),
   141  		FlushInterval:  aws.String("1m2s"),
   142  		OutputColumnID: aws.Bool(false),
   143  	}
   144  	c := NewConfig()
   145  	err = c.Apply(context.TODO(), sinkURI, replicaConfig)
   146  	require.NoError(t, err)
   147  	require.Equal(t, 12, c.WorkerCount)
   148  	require.Equal(t, 1485760, c.FileSize)
   149  	require.Equal(t, "1m2s", c.FlushInterval.String())
   150  
   151  	// test override
   152  	uri = "s3://bucket/prefix?worker-count=64&flush-interval=2m2s&file-size=33554432"
   153  	sinkURI, err = url.Parse(uri)
   154  	require.NoError(t, err)
   155  	replicaConfig.Sink.CloudStorageConfig = &config.CloudStorageConfig{
   156  		WorkerCount:    aws.Int(12),
   157  		FileSize:       aws.Int(10485760),
   158  		FlushInterval:  aws.String("1m2s"),
   159  		OutputColumnID: aws.Bool(false),
   160  	}
   161  	c = NewConfig()
   162  	err = c.Apply(context.TODO(), sinkURI, replicaConfig)
   163  	require.NoError(t, err)
   164  	require.Equal(t, 64, c.WorkerCount)
   165  	require.Equal(t, 33554432, c.FileSize)
   166  	require.Equal(t, "2m2s", c.FlushInterval.String())
   167  }