github.com/filecoin-project/bacalhau@v0.3.23-0.20230228154132-45c989550ace/pkg/test/devstack/utils.go (about) 1 package devstack 2 3 import ( 4 "context" 5 "fmt" 6 "os" 7 "testing" 8 "time" 9 10 "github.com/filecoin-project/bacalhau/pkg/devstack" 11 "github.com/filecoin-project/bacalhau/pkg/executor" 12 noop_executor "github.com/filecoin-project/bacalhau/pkg/executor/noop" 13 executor_util "github.com/filecoin-project/bacalhau/pkg/executor/util" 14 "github.com/filecoin-project/bacalhau/pkg/job" 15 _ "github.com/filecoin-project/bacalhau/pkg/logger" 16 "github.com/filecoin-project/bacalhau/pkg/model" 17 "github.com/filecoin-project/bacalhau/pkg/node" 18 "github.com/filecoin-project/bacalhau/pkg/requester/publicapi" 19 noop_storage "github.com/filecoin-project/bacalhau/pkg/storage/noop" 20 "github.com/filecoin-project/bacalhau/pkg/system" 21 "github.com/stretchr/testify/require" 22 ) 23 24 func prepareFolderWithFiles(t *testing.T, fileCount int) string { //nolint:unused 25 basePath := t.TempDir() 26 for i := 0; i < fileCount; i++ { 27 err := os.WriteFile( 28 fmt.Sprintf("%s/%d.txt", basePath, i), 29 []byte(fmt.Sprintf("hello %d", i)), 30 os.ModePerm, 31 ) 32 require.NoError(t, err) 33 } 34 return basePath 35 } 36 37 type DeterministicVerifierTestArgs struct { 38 NodeCount int 39 ShardCount int 40 BadActors int 41 Confidence int 42 ExpectedPassed int 43 ExpectedFailed int 44 } 45 46 func RunDeterministicVerifierTest( //nolint:funlen 47 ctx context.Context, 48 t *testing.T, 49 submitJob func( 50 apiClient *publicapi.RequesterAPIClient, 51 args DeterministicVerifierTestArgs, 52 ) (string, error), 53 args DeterministicVerifierTestArgs, 54 ) { 55 cm := system.NewCleanupManager() 56 defer cm.Cleanup(ctx) 57 58 options := devstack.DevStackOptions{ 59 NumberOfHybridNodes: args.NodeCount, 60 NumberOfBadComputeActors: args.BadActors, 61 } 62 63 storageProvidersFactory := devstack.NewNoopStorageProvidersFactoryWithConfig(noop_storage.StorageConfig{ 64 ExternalHooks: noop_storage.StorageConfigExternalHooks{ 65 Explode: func(ctx context.Context, storageSpec model.StorageSpec) ([]model.StorageSpec, error) { 66 var results []model.StorageSpec 67 for i := 0; i < args.ShardCount; i++ { 68 results = append(results, model.StorageSpec{ 69 StorageSource: model.StorageSourceIPFS, 70 CID: fmt.Sprintf("123%d", i), 71 Path: fmt.Sprintf("/data/file%d.txt", i), 72 }) 73 } 74 return results, nil 75 }, 76 }, 77 }) 78 79 executorsFactory := node.ExecutorsFactoryFunc(func( 80 ctx context.Context, nodeConfig node.NodeConfig) (executor.ExecutorProvider, error) { 81 return executor_util.NewNoopExecutors(noop_executor.ExecutorConfig{ 82 ExternalHooks: noop_executor.ExecutorConfigExternalHooks{ 83 JobHandler: func(ctx context.Context, shard model.JobShard, resultsDir string) (*model.RunCommandResult, error) { 84 runOutput := &model.RunCommandResult{} 85 runOutput.STDOUT = fmt.Sprintf("hello world %d", shard.Index) 86 if nodeConfig.ComputeConfig.SimulatorConfig.IsBadActor { 87 runOutput.STDOUT = fmt.Sprintf("i am bad and deserve to fail %d", shard.Index) 88 } 89 err := os.WriteFile(fmt.Sprintf("%s/stdout", resultsDir), []byte(runOutput.STDOUT), 0600) //nolint:gomnd 90 if err != nil { 91 runOutput.ErrorMsg = err.Error() 92 } 93 94 // Adding explicit error for consistency in function signatures 95 return runOutput, err 96 }, 97 }, 98 }), nil 99 }) 100 101 injector := node.NewStandardNodeDependencyInjector() 102 injector.ExecutorsFactory = executorsFactory 103 injector.StorageProvidersFactory = storageProvidersFactory 104 105 stack, err := devstack.NewDevStack( 106 ctx, 107 cm, 108 options, 109 node.NewComputeConfigWithDefaults(), 110 node.NewRequesterConfigWithDefaults(), 111 injector, 112 ) 113 require.NoError(t, err) 114 115 // wait for other nodes to catch up 116 time.Sleep(time.Second * 1) 117 apiURI := stack.Nodes[0].APIServer.GetURI() 118 apiClient := publicapi.NewRequesterAPIClient(apiURI) 119 120 jobID, err := submitJob(apiClient, args) 121 require.NoError(t, err) 122 123 resolver := apiClient.GetJobStateResolver() 124 125 err = resolver.Wait( 126 ctx, 127 jobID, 128 job.WaitForTerminalStates(), 129 ) 130 require.NoError(t, err) 131 132 state, err := resolver.GetJobState(ctx, jobID) 133 require.NoError(t, err) 134 135 verifiedCount := 0 136 failedCount := 0 137 138 for _, shard := range state.Shards { 139 for _, execution := range shard.Executions { //nolint:gocritic 140 require.True(t, execution.VerificationResult.Complete) 141 if execution.VerificationResult.Result { 142 verifiedCount++ 143 } else { 144 failedCount++ 145 } 146 } 147 } 148 149 require.Equal(t, args.ExpectedPassed*args.ShardCount, verifiedCount, "verified count should be correct") 150 require.Equal(t, args.ExpectedFailed*args.ShardCount, failedCount, "failed count should be correct") 151 }