Skip to content

Commit b304999

Browse files
committed
Add kernel reader tests in optimization test
1 parent 0cb531b commit b304999

File tree

9 files changed

+141
-10
lines changed

9 files changed

+141
-10
lines changed

internal/kernelparams/kernelparams.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -94,8 +94,8 @@ func atomicFileWrite(kernelParamsFile string, data []byte) error {
9494
return os.Rename(tempFile.Name(), kernelParamsFile)
9595
}
9696

97-
// pathForParam returns the sysfs path for a given parameter.
98-
func pathForParam(name ParamName, major, minor uint32) (string, error) {
97+
// PathForParam returns the sysfs path for a given parameter.
98+
func PathForParam(name ParamName, major, minor uint32) (string, error) {
9999
switch name {
100100
case MaxReadAheadKb:
101101
return fmt.Sprintf("/sys/class/bdi/%d:%d/read_ahead_kb", major, minor), nil
@@ -159,7 +159,7 @@ func (c *KernelParamsConfig) applyDirectly(mountPoint string) {
159159
return
160160
}
161161
for _, p := range c.Parameters {
162-
path, err := pathForParam(p.Name, major, minor)
162+
path, err := PathForParam(p.Name, major, minor)
163163
if err != nil {
164164
logger.Warnf("Unable to update setting %q to value %q for the mount point %q due to err: %v", p.Name, p.Value, mountPoint, err)
165165
continue

internal/kernelparams/kernelparams_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ func TestPathForParam(t *testing.T) {
7979
for _, tt := range tests {
8080
t.Run(string(tt.name), func(t *testing.T) {
8181

82-
path, err := pathForParam(tt.name, tt.major, tt.minor)
82+
path, err := PathForParam(tt.name, tt.major, tt.minor)
8383

8484
if tt.expectErr {
8585
assert.Error(t, err)

tools/integration_tests/flag_optimizations/optimization_test.go

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,21 @@
1515
package flag_optimizations
1616

1717
import (
18+
"bufio"
19+
"encoding/json"
20+
"fmt"
1821
"os"
1922
"path/filepath"
2023
"strings"
2124
"testing"
2225

26+
"github.com/googlecloudplatform/gcsfuse/v3/cfg"
27+
"github.com/googlecloudplatform/gcsfuse/v3/internal/kernelparams"
2328
"github.com/googlecloudplatform/gcsfuse/v3/tools/integration_tests/util/client"
2429
"github.com/googlecloudplatform/gcsfuse/v3/tools/integration_tests/util/setup"
2530
"github.com/stretchr/testify/assert"
2631
"github.com/stretchr/testify/require"
32+
"golang.org/x/sys/unix"
2733
)
2834

2935
////////////////////////////////////////////////////////////////////////
@@ -35,6 +41,44 @@ func tearDownOptimizationTest(t *testing.T) {
3541
setup.UnmountGCSFuseWithConfig(&testEnv.cfg)
3642
}
3743

44+
////////////////////////////////////////////////////////////////////////
45+
// Helpers
46+
////////////////////////////////////////////////////////////////////////
47+
48+
func validateConfigValues(t *testing.T, logFile string, requiredLogKey string, expectedConfig map[string]interface{}) {
49+
// Open log file to verify config
50+
file, err := os.Open(logFile)
51+
require.NoError(t, err)
52+
defer file.Close()
53+
54+
var configFound bool
55+
scanner := bufio.NewScanner(file)
56+
for scanner.Scan() {
57+
var entry map[string]interface{}
58+
if err := json.Unmarshal(scanner.Bytes(), &entry); err != nil {
59+
// Skip non-JSON lines (e.g. command invocation)
60+
continue
61+
}
62+
// Check if the log entry contains the required key
63+
if _, ok := entry[requiredLogKey]; !ok {
64+
continue
65+
}
66+
67+
if fullConfigMap, ok := entry["Full Config"].(map[string]interface{}); ok {
68+
configFound = true
69+
for key, expectedVal := range expectedConfig {
70+
var actualVal interface{}
71+
if valMap, ok := fullConfigMap[key].(map[string]interface{}); ok {
72+
actualVal = valMap["final_value"]
73+
}
74+
assert.EqualValues(t, expectedVal, actualVal, "Config %q mismatch", key)
75+
}
76+
break
77+
}
78+
}
79+
assert.True(t, configFound, "GCSFuse Config log not found")
80+
}
81+
3882
////////////////////////////////////////////////////////////////////////
3983
// Test Functions
4084
////////////////////////////////////////////////////////////////////////
@@ -64,6 +108,67 @@ func TestImplicitDirsNotEnabled(t *testing.T) {
64108
}
65109
}
66110

111+
func TestZonalBucketOptimizations_LogVerification(t *testing.T) {
112+
if setup.IsDynamicMount(testEnv.mountDir, testEnv.rootDir) {
113+
t.Skip("Skipping test for dynamic mounting")
114+
}
115+
116+
flagsSet := setup.BuildFlagSets(testEnv.cfg, testEnv.bucketType, t.Name())
117+
for _, flags := range flagsSet {
118+
t.Run(strings.Join(flags, "_"), func(t *testing.T) {
119+
mustMountGCSFuseAndSetupTestDir(flags, testEnv.ctx, testEnv.storageClient)
120+
defer tearDownOptimizationTest(t)
121+
122+
expectedConfig := map[string]interface{}{
123+
"file-system.enable-kernel-reader": true,
124+
"file-system.max-read-ahead-kb": 16384,
125+
"file-system.max-background": cfg.DefaultMaxBackground(),
126+
"file-system.congestion-threshold": cfg.DefaultCongestionThreshold(),
127+
}
128+
validateConfigValues(t, testEnv.cfg.LogFile, "Applied optimizations for bucket-type: ", expectedConfig)
129+
})
130+
}
131+
}
132+
133+
func TestZonalBucketOptimizations_KernelParamVerification(t *testing.T) {
134+
if setup.IsDynamicMount(testEnv.mountDir, testEnv.rootDir) {
135+
t.Skip("Skipping test for dynamic mounting")
136+
}
137+
138+
flagsSet := setup.BuildFlagSets(testEnv.cfg, testEnv.bucketType, t.Name())
139+
for _, flags := range flagsSet {
140+
t.Run(strings.Join(flags, "_"), func(t *testing.T) {
141+
mustMountGCSFuseAndSetupTestDir(flags, testEnv.ctx, testEnv.storageClient)
142+
defer tearDownOptimizationTest(t)
143+
144+
// Verify kernel parameters in /sys
145+
var stat unix.Stat_t
146+
err := unix.Stat(setup.MntDir(), &stat)
147+
require.NoError(t, err)
148+
devMajor := unix.Major(stat.Dev)
149+
devMinor := unix.Minor(stat.Dev)
150+
readAheadPath, err := kernelparams.PathForParam(kernelparams.MaxReadAheadKb, devMajor, devMinor)
151+
require.NoError(t, err)
152+
maxBackgroundPath, err := kernelparams.PathForParam(kernelparams.MaxBackgroundRequests, devMajor, devMinor)
153+
require.NoError(t, err)
154+
congestionThresholdPath, err := kernelparams.PathForParam(kernelparams.CongestionWindowThreshold, devMajor, devMinor)
155+
require.NoError(t, err)
156+
expected := map[string]string{
157+
readAheadPath: "16384",
158+
maxBackgroundPath: fmt.Sprintf("%d", cfg.DefaultMaxBackground()),
159+
congestionThresholdPath: fmt.Sprintf("%d", cfg.DefaultCongestionThreshold()),
160+
}
161+
162+
for path, val := range expected {
163+
content, err := os.ReadFile(path)
164+
165+
require.NoError(t, err)
166+
assert.Equal(t, val, strings.TrimSpace(string(content)))
167+
}
168+
})
169+
}
170+
}
171+
67172
func TestRenameDirLimitNotSet(t *testing.T) {
68173
flagsSet := setup.BuildFlagSets(testEnv.cfg, testEnv.bucketType, t.Name())
69174
for _, flags := range flagsSet {

tools/integration_tests/flag_optimizations/setup_test.go

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -106,8 +106,8 @@ func TestMain(m *testing.M) {
106106
cfg.FlagOptimizations[0].TestBucket = setup.TestBucket()
107107
cfg.FlagOptimizations[0].GKEMountedDirectory = setup.MountedDirectory()
108108
cfg.FlagOptimizations[0].LogFile = setup.LogFile()
109-
// Initialize the slice to hold 6 specific test configurations
110-
cfg.FlagOptimizations[0].Configs = make([]test_suite.ConfigItem, 5)
109+
// Initialize the slice to hold 7 specific test configurations
110+
cfg.FlagOptimizations[0].Configs = make([]test_suite.ConfigItem, 7)
111111
cfg.FlagOptimizations[0].Configs[0].Run = "TestMountFails"
112112
cfg.FlagOptimizations[0].Configs[0].Flags = []string{"--profile=unknown-profile"}
113113
cfg.FlagOptimizations[0].Configs[0].Compatible = map[string]bool{"flat": true, "hns": true, "zonal": true}
@@ -140,6 +140,14 @@ func TestMain(m *testing.M) {
140140
}
141141
cfg.FlagOptimizations[0].Configs[4].Compatible = map[string]bool{"flat": true, "hns": false, "zonal": false}
142142
cfg.FlagOptimizations[0].Configs[4].RunOnGKE = true
143+
cfg.FlagOptimizations[0].Configs[5].Run = "TestZonalBucketOptimizations_LogVerification"
144+
cfg.FlagOptimizations[0].Configs[5].Flags = []string{"--log-severity=info"}
145+
cfg.FlagOptimizations[0].Configs[5].Compatible = map[string]bool{"flat": false, "hns": false, "zonal": true}
146+
cfg.FlagOptimizations[0].Configs[5].RunOnGKE = true
147+
cfg.FlagOptimizations[0].Configs[6].Run = "TestZonalBucketOptimizations_KernelParamVerification"
148+
cfg.FlagOptimizations[0].Configs[6].Flags = []string{"--log-severity=info"}
149+
cfg.FlagOptimizations[0].Configs[6].Compatible = map[string]bool{"flat": false, "hns": false, "zonal": true}
150+
cfg.FlagOptimizations[0].Configs[6].RunOnGKE = true
143151
}
144152

145153
testEnv.ctx = context.Background()

tools/integration_tests/test_config.yaml

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -685,6 +685,22 @@ flag_optimizations:
685685
hns: false
686686
zonal: false
687687
run_on_gke: true
688+
- run: TestZonalBucketOptimizations_LogVerification
689+
flags:
690+
- "--enable-kernel-reader=true"
691+
compatible:
692+
flat: false
693+
hns: false
694+
zonal: true
695+
run_on_gke: true
696+
- run: TestZonalBucketOptimizations_KernelParamVerification
697+
flags:
698+
- "--enable-kernel-reader=true"
699+
compatible:
700+
flat: false
701+
hns: false
702+
zonal: true
703+
run_on_gke: true
688704

689705
unsupported_path:
690706
- mounted_directory: "${MOUNTED_DIR}"

tools/integration_tests/util/mounting/only_dir_mounting/only_dir_mounting.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,6 @@ func MountGcsfuseWithOnlyDirWithConfigFile(config *test_suite.TestConfig, flags
4343
setup.OnlyDirMounted(),
4444
"--log-severity=trace",
4545
"--log-file=" + config.LogFile,
46-
"--enable-kernel-reader=false",
4746
config.TestBucket,
4847
config.GCSFuseMountedDirectory}
4948

tools/integration_tests/util/mounting/persistent_mounting/perisistent_mounting.go

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,6 @@ func mountGcsfuseWithPersistentMountingWithConfigFile(config *test_suite.TestCon
4949
"log_severity=trace",
5050
"-o",
5151
"log_file=" + config.LogFile,
52-
"-o",
53-
"enable-kernel-reader=false",
5452
}
5553

5654
persistentMountingArgs := makePersistentMountingArgs(flags)

tools/integration_tests/util/mounting/static_mounting/static_mounting.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,6 @@ func MountGcsfuseWithStaticMountingWithConfigFile(config *test_suite.TestConfig,
4444

4545
defaultArg = append(defaultArg, "--log-severity=trace",
4646
"--log-file="+config.LogFile,
47-
"--enable-kernel-reader=false",
4847
config.TestBucket,
4948
config.GCSFuseMountedDirectory)
5049

tools/integration_tests/util/setup/setup.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -827,6 +827,12 @@ func GetGCERegion(gceZone string) (string, error) {
827827
return region, nil
828828
}
829829

830+
// IsDynamicMount returns true if the mount is dynamic.
831+
// In dynamic mounts, rootDir contains all buckets, and mountDir is the specific bucket directory.
832+
func IsDynamicMount(mountDir, rootDir string) bool {
833+
return mountDir != rootDir
834+
}
835+
830836
// ExtractServiceVersionFromFlags parses the cloud-profiler-label from a slice of flag strings.
831837
func ExtractServiceVersionFromFlags(flags []string) string {
832838
// Regex to find --cloud-profiler-label=some_value or --cloud-profiler-label some_value

0 commit comments

Comments
 (0)