mirror of
https://github.com/fatedier/frp.git
synced 2026-03-08 02:49:10 +08:00
218 lines
5.7 KiB
Go
218 lines
5.7 KiB
Go
// Copyright 2026 The frp Authors
|
|
//
|
|
// Licensed 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 source
|
|
|
|
import (
|
|
"path/filepath"
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/require"
|
|
|
|
v1 "github.com/fatedier/frp/pkg/config/v1"
|
|
)
|
|
|
|
// mockProxy creates a TCP proxy config for testing
|
|
func mockProxy(name string) v1.ProxyConfigurer {
|
|
cfg := &v1.TCPProxyConfig{}
|
|
cfg.Name = name
|
|
cfg.Type = "tcp"
|
|
cfg.LocalPort = 8080
|
|
cfg.RemotePort = 9090
|
|
return cfg
|
|
}
|
|
|
|
// mockVisitor creates a STCP visitor config for testing
|
|
func mockVisitor(name string) v1.VisitorConfigurer {
|
|
cfg := &v1.STCPVisitorConfig{}
|
|
cfg.Name = name
|
|
cfg.Type = "stcp"
|
|
cfg.ServerName = "test-server"
|
|
return cfg
|
|
}
|
|
|
|
func newTestStoreSource(t *testing.T) *StoreSource {
|
|
t.Helper()
|
|
|
|
path := filepath.Join(t.TempDir(), "store.json")
|
|
storeSource, err := NewStoreSource(StoreSourceConfig{Path: path})
|
|
require.NoError(t, err)
|
|
return storeSource
|
|
}
|
|
|
|
func newTestAggregator(t *testing.T, storeSource *StoreSource) *Aggregator {
|
|
t.Helper()
|
|
|
|
configSource := NewConfigSource()
|
|
agg := NewAggregator(configSource)
|
|
if storeSource != nil {
|
|
agg.SetStoreSource(storeSource)
|
|
}
|
|
return agg
|
|
}
|
|
|
|
func TestNewAggregator_CreatesConfigSourceWhenNil(t *testing.T) {
|
|
require := require.New(t)
|
|
|
|
agg := NewAggregator(nil)
|
|
require.NotNil(agg)
|
|
require.NotNil(agg.ConfigSource())
|
|
require.Nil(agg.StoreSource())
|
|
}
|
|
|
|
func TestNewAggregator_WithoutStore(t *testing.T) {
|
|
require := require.New(t)
|
|
|
|
configSource := NewConfigSource()
|
|
agg := NewAggregator(configSource)
|
|
require.NotNil(agg)
|
|
require.Same(configSource, agg.ConfigSource())
|
|
require.Nil(agg.StoreSource())
|
|
}
|
|
|
|
func TestNewAggregator_WithStore(t *testing.T) {
|
|
require := require.New(t)
|
|
|
|
storeSource := newTestStoreSource(t)
|
|
configSource := NewConfigSource()
|
|
agg := NewAggregator(configSource)
|
|
agg.SetStoreSource(storeSource)
|
|
|
|
require.Same(configSource, agg.ConfigSource())
|
|
require.Same(storeSource, agg.StoreSource())
|
|
}
|
|
|
|
func TestAggregator_SetStoreSource_Overwrite(t *testing.T) {
|
|
require := require.New(t)
|
|
|
|
agg := newTestAggregator(t, nil)
|
|
first := newTestStoreSource(t)
|
|
second := newTestStoreSource(t)
|
|
|
|
agg.SetStoreSource(first)
|
|
require.Same(first, agg.StoreSource())
|
|
|
|
agg.SetStoreSource(second)
|
|
require.Same(second, agg.StoreSource())
|
|
|
|
agg.SetStoreSource(nil)
|
|
require.Nil(agg.StoreSource())
|
|
}
|
|
|
|
func TestAggregator_MergeBySourceOrder(t *testing.T) {
|
|
require := require.New(t)
|
|
|
|
storeSource := newTestStoreSource(t)
|
|
agg := newTestAggregator(t, storeSource)
|
|
|
|
configSource := agg.ConfigSource()
|
|
|
|
configShared := mockProxy("shared").(*v1.TCPProxyConfig)
|
|
configShared.LocalPort = 1111
|
|
configOnly := mockProxy("only-in-config").(*v1.TCPProxyConfig)
|
|
configOnly.LocalPort = 1112
|
|
|
|
err := configSource.ReplaceAll([]v1.ProxyConfigurer{configShared, configOnly}, nil)
|
|
require.NoError(err)
|
|
|
|
storeShared := mockProxy("shared").(*v1.TCPProxyConfig)
|
|
storeShared.LocalPort = 2222
|
|
storeOnly := mockProxy("only-in-store").(*v1.TCPProxyConfig)
|
|
storeOnly.LocalPort = 2223
|
|
err = storeSource.AddProxy(storeShared)
|
|
require.NoError(err)
|
|
err = storeSource.AddProxy(storeOnly)
|
|
require.NoError(err)
|
|
|
|
proxies, visitors, err := agg.Load()
|
|
require.NoError(err)
|
|
require.Len(visitors, 0)
|
|
require.Len(proxies, 3)
|
|
|
|
var sharedProxy *v1.TCPProxyConfig
|
|
for _, p := range proxies {
|
|
if p.GetBaseConfig().Name == "shared" {
|
|
sharedProxy = p.(*v1.TCPProxyConfig)
|
|
break
|
|
}
|
|
}
|
|
require.NotNil(sharedProxy)
|
|
require.Equal(2222, sharedProxy.LocalPort)
|
|
}
|
|
|
|
func TestAggregator_DisabledEntryIsSourceLocalFilter(t *testing.T) {
|
|
require := require.New(t)
|
|
|
|
storeSource := newTestStoreSource(t)
|
|
agg := newTestAggregator(t, storeSource)
|
|
configSource := agg.ConfigSource()
|
|
|
|
lowProxy := mockProxy("shared-proxy").(*v1.TCPProxyConfig)
|
|
lowProxy.LocalPort = 1111
|
|
err := configSource.ReplaceAll([]v1.ProxyConfigurer{lowProxy}, nil)
|
|
require.NoError(err)
|
|
|
|
disabled := false
|
|
highProxy := mockProxy("shared-proxy").(*v1.TCPProxyConfig)
|
|
highProxy.LocalPort = 2222
|
|
highProxy.Enabled = &disabled
|
|
err = storeSource.AddProxy(highProxy)
|
|
require.NoError(err)
|
|
|
|
proxies, visitors, err := agg.Load()
|
|
require.NoError(err)
|
|
require.Len(proxies, 1)
|
|
require.Len(visitors, 0)
|
|
|
|
proxy := proxies[0].(*v1.TCPProxyConfig)
|
|
require.Equal("shared-proxy", proxy.Name)
|
|
require.Equal(1111, proxy.LocalPort)
|
|
}
|
|
|
|
func TestAggregator_VisitorMerge(t *testing.T) {
|
|
require := require.New(t)
|
|
|
|
storeSource := newTestStoreSource(t)
|
|
agg := newTestAggregator(t, storeSource)
|
|
|
|
err := agg.ConfigSource().ReplaceAll(nil, []v1.VisitorConfigurer{mockVisitor("visitor1")})
|
|
require.NoError(err)
|
|
err = storeSource.AddVisitor(mockVisitor("visitor2"))
|
|
require.NoError(err)
|
|
|
|
_, visitors, err := agg.Load()
|
|
require.NoError(err)
|
|
require.Len(visitors, 2)
|
|
}
|
|
|
|
func TestAggregator_Load_ReturnsDefensiveCopies(t *testing.T) {
|
|
require := require.New(t)
|
|
|
|
agg := newTestAggregator(t, nil)
|
|
err := agg.ConfigSource().ReplaceAll([]v1.ProxyConfigurer{mockProxy("ssh")}, nil)
|
|
require.NoError(err)
|
|
|
|
proxies, _, err := agg.Load()
|
|
require.NoError(err)
|
|
require.Len(proxies, 1)
|
|
require.Equal("ssh", proxies[0].GetBaseConfig().Name)
|
|
|
|
proxies[0].GetBaseConfig().Name = "alice.ssh"
|
|
|
|
proxies2, _, err := agg.Load()
|
|
require.NoError(err)
|
|
require.Len(proxies2, 1)
|
|
require.Equal("ssh", proxies2[0].GetBaseConfig().Name)
|
|
}
|