Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
101 changes: 69 additions & 32 deletions tools/integration_tests/stale_handle/setup_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,13 @@
// 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
// 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 stale_handle

import (
Expand All @@ -24,60 +23,98 @@ import (
"github.com/googlecloudplatform/gcsfuse/v3/tools/integration_tests/util/client"
"github.com/googlecloudplatform/gcsfuse/v3/tools/integration_tests/util/mounting/static_mounting"
"github.com/googlecloudplatform/gcsfuse/v3/tools/integration_tests/util/setup"
"github.com/googlecloudplatform/gcsfuse/v3/tools/integration_tests/util/test_suite"
)

const (
testDirName = "StaleHandleTest"
)

var (
testEnv env
mountFunc func(*test_suite.TestConfig, []string) error
)

type env struct {
storageClient *storage.Client
ctx context.Context
rootDir string
mountFunc func([]string) error
flagsSet [][]string
)
testDirPath string
cfg *test_suite.TestConfig
bucketType string
}

////////////////////////////////////////////////////////////////////////
// TestMain
////////////////////////////////////////////////////////////////////////

func TestMain(m *testing.M) {
setup.ParseSetUpFlags()
setup.ExitWithFailureIfBothTestBucketAndMountedDirectoryFlagsAreNotSet()

// Create common storage client to be used in test.
ctx = context.Background()
closeStorageClient := client.CreateStorageClientWithCancel(&ctx, &storageClient)
defer func() {
err := closeStorageClient()
if err != nil {
log.Fatalf("closeStorageClient failed: %v", err)

// 1. Load and parse the common configuration.
cfg := test_suite.ReadConfigFile(setup.ConfigFile())
if len(cfg.StaleHandle) == 0 {
log.Println("No configuration found for stale_handle tests in config. Using flags instead.")
// Populate the config manually.
cfg.StaleHandle = make([]test_suite.TestConfig, 1)
cfg.StaleHandle[0].TestBucket = setup.TestBucket()
cfg.StaleHandle[0].GKEMountedDirectory = setup.MountedDirectory()
cfg.StaleHandle[0].LogFile = setup.LogFile()
cfg.StaleHandle[0].Configs = make([]test_suite.ConfigItem, 4)
cfg.StaleHandle[0].Configs[0].Flags = []string{
"--metadata-cache-ttl-secs=0 --write-block-size-mb=1 --write-max-blocks-per-file=1",
"--metadata-cache-ttl-secs=0 --write-block-size-mb=1 --write-max-blocks-per-file=1 --client-protocol=grpc",
}
}()
cfg.StaleHandle[0].Configs[0].Compatible = map[string]bool{"flat": true, "hns": true, "zonal": true}
cfg.StaleHandle[0].Configs[0].Run = "TestStaleFileHandleLocalFileTestStreamingWritesEnabled"

// To run mountedDirectory tests, we need both testBucket and mountedDirectory
// flags to be set, as stale handle tests validates content from the bucket.
// Note: These tests by default can only be run for non streaming mounts.
if setup.AreBothMountedDirectoryAndTestBucketFlagsSet() {
rootDir = setup.MountedDirectory()
setup.RunTestsForMountedDirectoryFlag(m)
return
cfg.StaleHandle[0].Configs[1].Flags = []string{
"--metadata-cache-ttl-secs=0 --enable-streaming-writes=false",
"--metadata-cache-ttl-secs=0 --enable-streaming-writes=false --client-protocol=grpc",
}
cfg.StaleHandle[0].Configs[1].Compatible = map[string]bool{"flat": true, "hns": true, "zonal": true}
cfg.StaleHandle[0].Configs[1].Run = "TestStaleFileHandleLocalFileTestStreamingWritesDisabled"

cfg.StaleHandle[0].Configs[2].Flags = []string{
"--metadata-cache-ttl-secs=0 --write-block-size-mb=1 --write-max-blocks-per-file=1",
"--metadata-cache-ttl-secs=0 --write-block-size-mb=1 --write-max-blocks-per-file=1 --client-protocol=grpc",
}
cfg.StaleHandle[0].Configs[2].Compatible = map[string]bool{"flat": true, "hns": true, "zonal": true}
cfg.StaleHandle[0].Configs[2].Run = "TestStaleFileHandleEmptyGcsFileTestStreamingWritesEnabled"

cfg.StaleHandle[0].Configs[3].Flags = []string{
"--metadata-cache-ttl-secs=0 --enable-streaming-writes=false",
"--metadata-cache-ttl-secs=0 --enable-streaming-writes=false --client-protocol=grpc",
}
cfg.StaleHandle[0].Configs[3].Compatible = map[string]bool{"flat": true, "hns": true, "zonal": true}
cfg.StaleHandle[0].Configs[3].Run = "TestStaleFileHandleEmptyGcsFileTestStreamingWritesDisabled"
}

// Set up test directory.
setup.SetUpTestDirForTestBucketFlag()
rootDir = setup.MntDir()
testEnv.ctx = context.Background()
testEnv.cfg = &cfg.StaleHandle[0]
testEnv.bucketType = setup.TestEnvironment(testEnv.ctx, testEnv.cfg)

flagsSet = [][]string{
{"--metadata-cache-ttl-secs=0", "--enable-streaming-writes=false"},
{"--metadata-cache-ttl-secs=0", "--write-block-size-mb=1", "--write-max-blocks-per-file=1"},
// 2. Create storage client before running tests.
var err error
testEnv.storageClient, err = client.CreateStorageClient(testEnv.ctx)
if err != nil {
log.Printf("Error creating storage client: %v\n", err)
os.Exit(1)
}
// Run all tests with GRPC.
setup.AppendFlagsToAllFlagsInTheFlagsSet(&flagsSet, "--client-protocol=grpc", "")
defer testEnv.storageClient.Close()

// 3. To run mountedDirectory tests, we need both testBucket and mountedDirectory
// flags to be set, as stale handle tests validates content from the bucket.
// Note: These tests by default can only be run for non streaming mounts.
if testEnv.cfg.GKEMountedDirectory != "" && testEnv.cfg.TestBucket != "" {
os.Exit(setup.RunTestsForMountedDirectory(testEnv.cfg.GKEMountedDirectory, m))
}

// Run tests for testBucket
setup.SetUpTestDirForTestBucket(testEnv.cfg)

log.Println("Running static mounting tests...")
mountFunc = static_mounting.MountGcsfuseWithStaticMounting
mountFunc = static_mounting.MountGcsfuseWithStaticMountingWithConfigFile
successCode := m.Run()

os.Exit(successCode)
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
// 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
// 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,
Expand Down Expand Up @@ -33,28 +33,23 @@ import (
// //////////////////////////////////////////////////////////////////////

type staleFileHandleCommon struct {
suite.Suite
flags []string
f1 *os.File
fileName string
data string
testDirPath string
isStreamingWritesEnabled bool
isLocal bool
suite.Suite
}

// //////////////////////////////////////////////////////////////////////
// Helpers
// //////////////////////////////////////////////////////////////////////
func (s *staleFileHandleCommon) SetupSuite() {
setup.MountGCSFuseWithGivenMountFunc(s.flags, mountFunc)
s.testDirPath = setup.SetupTestDirectory(testDirName)
setup.MountGCSFuseWithGivenMountWithConfigFunc(testEnv.cfg, s.flags, mountFunc)
testEnv.testDirPath = SetupTestDirectory(testEnv.ctx, testEnv.storageClient, testDirName)
s.data = setup.GenerateRandomString(5 * util.MiB)
}

func (s *staleFileHandleCommon) TearDownSuite() {
setup.UnmountGCSFuse(rootDir)
setup.SaveGCSFuseLogFileInCaseOfFailure(s.T())
setup.UnmountGCSFuseWithConfig(testEnv.cfg)
}

////////////////////////////////////////////////////////////////////////
Expand All @@ -69,13 +64,14 @@ func (s *staleFileHandleCommon) TestClobberedFileSyncAndCloseThrowsStaleFileHand
// Dirty the file by giving it some contents.
operations.WriteWithoutClose(s.f1, s.data, s.T())
// Clobber file by replacing the underlying object with a new generation.
err := WriteToObject(ctx, storageClient, path.Join(testDirName, s.fileName), FileContents, storage.Conditions{})
err := WriteToObject(testEnv.ctx, testEnv.storageClient, path.Join(testDirName, s.fileName), FileContents, storage.Conditions{})
assert.NoError(s.T(), err)

operations.ValidateSyncGivenThatFileIsClobbered(s.T(), s.f1, s.isStreamingWritesEnabled)

err = s.f1.Close()
operations.ValidateESTALEError(s.T(), err)
ValidateObjectContentsFromGCS(ctx, storageClient, testDirName, s.fileName, FileContents, s.T())
ValidateObjectContentsFromGCS(testEnv.ctx, testEnv.storageClient, testDirName, s.fileName, FileContents, s.T())
}

func (s *staleFileHandleCommon) TestFileDeletedLocallySyncAndCloseDoNotThrowError() {
Expand All @@ -91,7 +87,7 @@ func (s *staleFileHandleCommon) TestFileDeletedLocallySyncAndCloseDoNotThrowErro
operations.WriteWithoutClose(s.f1, s.data, s.T())
operations.SyncFile(s.f1, s.T())
operations.CloseFileShouldNotThrowError(s.T(), s.f1)
ValidateObjectNotFoundErrOnGCS(ctx, storageClient, testDirName, s.fileName, s.T())
ValidateObjectNotFoundErrOnGCS(testEnv.ctx, testEnv.storageClient, testDirName, s.fileName, s.T())
}

func (s *staleFileHandleCommon) TestRenamedFileSyncAndCloseThrowsStaleFileHandleError() {
Expand All @@ -100,7 +96,7 @@ func (s *staleFileHandleCommon) TestRenamedFileSyncAndCloseThrowsStaleFileHandle
assert.NoError(s.T(), err)
newFile := "new" + s.fileName

err = operations.RenameFile(s.f1.Name(), path.Join(s.testDirPath, newFile))
err = operations.RenameFile(s.f1.Name(), path.Join(testEnv.testDirPath, newFile))

assert.NoError(s.T(), err)
_, err = s.f1.WriteString(s.data)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
// 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
// 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,
Expand All @@ -15,14 +15,13 @@
package stale_handle

import (
"log"
"path"
"slices"
"testing"

"github.com/googlecloudplatform/gcsfuse/v3/tools/integration_tests/util/operations"
"github.com/stretchr/testify/suite"

"github.com/googlecloudplatform/gcsfuse/v3/tools/integration_tests/util/setup"
"github.com/stretchr/testify/suite"
)

// //////////////////////////////////////////////////////////////////////
Expand All @@ -40,24 +39,47 @@ type staleFileHandleLocalFile struct {
func (s *staleFileHandleLocalFile) SetupTest() {
// Create a local file.
s.fileName = path.Base(s.T().Name()) + setup.GenerateRandomString(5)
s.f1 = operations.OpenFileWithODirect(s.T(), path.Join(s.testDirPath, s.fileName))
s.f1 = operations.OpenFileWithODirect(s.T(), path.Join(testEnv.testDirPath, s.fileName))
s.isLocal = true
}
func (s *staleFileHandleLocalFile) TearDownTest() {
setup.SaveGCSFuseLogFileInCaseOfFailure(s.T())
}

////////////////////////////////////////////////////////////////////////
// Test Function (Runs once before all tests)
////////////////////////////////////////////////////////////////////////

func TestStaleFileHandleLocalFileTest(t *testing.T) {
func TestStaleFileHandleLocalFileTestStreamingWritesEnabled(t *testing.T) {
// Run tests for mounted directory if the flag is set and return.
if setup.AreBothMountedDirectoryAndTestBucketFlagsSet() {
suite.Run(t, new(staleFileHandleLocalFile))
return
}

flagsSet := setup.BuildFlagSets(*testEnv.cfg, testEnv.bucketType, t.Name())
for _, flags := range flagsSet {
s := new(staleFileHandleLocalFile)
s.flags = flags
log.Printf("Running tests with flags: %s", s.flags)
s.isStreamingWritesEnabled = true
suite.Run(t, s)
}
}

func TestStaleFileHandleLocalFileTestStreamingWritesDisabled(t *testing.T) {
// Run tests for mounted directory if the flag is set and return.
if setup.AreBothMountedDirectoryAndTestBucketFlagsSet() {
suite.Run(t, new(staleFileHandleLocalFile))
return
}

flagsSet := setup.BuildFlagSets(*testEnv.cfg, testEnv.bucketType, t.Name())
for _, flags := range flagsSet {
s := new(staleFileHandleLocalFile)
s.flags = flags
s.isStreamingWritesEnabled = !slices.Contains(s.flags, "--enable-streaming-writes=false")
log.Printf("Running tests with flags: %s", s.flags)
s.isStreamingWritesEnabled = false
suite.Run(t, s)
}
}
Loading
Loading