diff --git a/Makefile b/Makefile index 828680f3..fa1fb912 100644 --- a/Makefile +++ b/Makefile @@ -21,6 +21,8 @@ GOBUILDTAGSOPT=-tags "$(GOBUILDTAGS)" ARANGODB ?= arangodb/enterprise:latest STARTER ?= arangodb/arangodb-starter:latest +# ARANGODB ?= public.ecr.aws/b0b8h2r4/enterprise-preview:2025-12-01-devel-d759089-amd64 +# STARTER ?= arangodb/arangodb-starter:local-test ifdef VERBOSE TESTVERBOSEOPTIONS := -v diff --git a/test/asyncjob_test.go b/test/asyncjob_test.go index 43d67b9e..9f0fc6b7 100644 --- a/test/asyncjob_test.go +++ b/test/asyncjob_test.go @@ -101,6 +101,9 @@ func TestAsyncJobListPending(t *testing.T) { EnsureVersion(t, ctx, c).CheckVersion(MinimumVersion("3.11.1")) skipResilientSingle(t) + // for disabling v8 tests + skipAboveVersion(c, "3.12.6-1", t) + db := ensureDatabase(ctx, c, databaseName("db", "async"), nil, t) defer func() { err := db.Remove(ctx) @@ -254,6 +257,9 @@ func TestAsyncJobDelete(t *testing.T) { }) t.Run("delete pending job", func(t *testing.T) { + // for disabling v8 tests + skipAboveVersion(c, "3.12.6-1", t) + idTransaction := runLongRequest(t, ctxAsync, db, 10, col.Name()) require.NotEmpty(t, idTransaction) @@ -275,6 +281,9 @@ func TestAsyncJobDelete(t *testing.T) { }) t.Run("delete expired jobs", func(t *testing.T) { + // for disabling v8 tests + skipAboveVersion(c, "3.12.6-1", t) + idTransaction := runLongRequest(t, ctxAsync, db, 10, col.Name()) require.NotEmpty(t, idTransaction) diff --git a/test/client_test.go b/test/client_test.go index 8142fd24..7c1309aa 100644 --- a/test/client_test.go +++ b/test/client_test.go @@ -670,3 +670,17 @@ func checkDBAccess(ctx context.Context, conn driver.Connection, dbName, username return nil } + +// skipAboveVersion skips the test if the current server version is greater than +// the given version. +func skipAboveVersion(c driver.Client, version driver.Version, t testEnv) driver.VersionInfo { + x, err := c.Version(nil) + if err != nil { + t.Fatalf("Failed to get version info: %s", describe(err)) + } + t.Logf("version info %s, version received %s", x.Version, version) + if x.Version.CompareTo(version) > 0 { + t.Skipf("Skipping above version '%s', got version '%s'", version, x.Version) + } + return x +} diff --git a/test/database_transaction_test.go b/test/database_transaction_test.go index 431ee4e9..edaaaeb4 100644 --- a/test/database_transaction_test.go +++ b/test/database_transaction_test.go @@ -33,7 +33,9 @@ import ( func TestDatabaseTransaction(t *testing.T) { c := createClient(t, nil) - skipBelowVersion(c, "3.2", t) + // for disabling v8 tests + skipAboveVersion(c, "3.12.6-1", t) + db := ensureDatabase(nil, c, "transaction_test", nil, t) defer func() { err := db.Remove(nil) diff --git a/v2/arangodb/client_admin.go b/v2/arangodb/client_admin.go index 3cd5673b..a4de05cb 100644 --- a/v2/arangodb/client_admin.go +++ b/v2/arangodb/client_admin.go @@ -60,7 +60,8 @@ type ClientAdmin interface { // options of the queried arangod instance. GetStartupConfigurationDescription(ctx context.Context) (map[string]interface{}, error) - // ReloadRoutingTable reloads the routing information from the _routing system collection. + // ReloadRoutingTable reloads the routing information from the _routing system + // collection, causing Foxx services to rebuild their routing table. ReloadRoutingTable(ctx context.Context, dbName string) error // ExecuteAdminScript executes JavaScript code on the server. diff --git a/v2/tests/admin_cluster_test.go b/v2/tests/admin_cluster_test.go index b94fa258..1e0f573f 100644 --- a/v2/tests/admin_cluster_test.go +++ b/v2/tests/admin_cluster_test.go @@ -369,9 +369,10 @@ func Test_ClusterResignLeadership(t *testing.T) { } func Test_ClusterStatistics(t *testing.T) { + requireClusterMode(t) + Wrap(t, func(t *testing.T, client arangodb.Client) { withContextT(t, defaultTestTimeout, func(ctx context.Context, tb testing.TB) { - requireClusterMode(t) skipBelowVersion(client, ctx, "3.7", t) // Detect DB-Server ID serverRole, err := client.ServerRole(ctx) diff --git a/v2/tests/admin_test.go b/v2/tests/admin_test.go index 2240b040..13df0868 100644 --- a/v2/tests/admin_test.go +++ b/v2/tests/admin_test.go @@ -143,7 +143,7 @@ func Test_GetServerStatus(t *testing.T) { func Test_GetDeploymentSupportInfo(t *testing.T) { Wrap(t, func(t *testing.T, client arangodb.Client) { - withContextT(t, time.Minute, func(ctx context.Context, t testing.TB) { + withContextT(t, defaultTestTimeout, func(ctx context.Context, t testing.TB) { serverRole, err := client.ServerRole(ctx) require.NoError(t, err) @@ -209,7 +209,8 @@ func Test_GetStartupConfiguration(t *testing.T) { func Test_ReloadRoutingTable(t *testing.T) { Wrap(t, func(t *testing.T, client arangodb.Client) { WithDatabase(t, client, nil, func(db arangodb.Database) { - withContextT(t, time.Minute, func(ctx context.Context, t testing.TB) { + withContextT(t, defaultTestTimeout, func(ctx context.Context, t testing.TB) { + requireV8Enabled(client, ctx, t) err := client.ReloadRoutingTable(ctx, db.Name()) require.NoError(t, err) }) @@ -221,6 +222,7 @@ func Test_ExecuteAdminScript(t *testing.T) { Wrap(t, func(t *testing.T, client arangodb.Client) { WithDatabase(t, client, nil, func(db arangodb.Database) { withContextT(t, defaultTestTimeout, func(ctx context.Context, tb testing.TB) { + requireV8Enabled(client, ctx, t) tests := []struct { name string script string @@ -275,7 +277,7 @@ func Test_CompactDatabases(t *testing.T) { // that may conflict with other tests and server role checks can be inconsistent in parallel execution. Wrap(t, func(t *testing.T, client arangodb.Client) { - withContextT(t, time.Minute, func(ctx context.Context, t testing.TB) { + withContextT(t, defaultTestTimeout, func(ctx context.Context, t testing.TB) { if !isNoAuth() { t.Skip("Skipping: superuser tests run only in no-auth mode (TEST_AUTH=none)") } @@ -376,7 +378,7 @@ func validateTLSResponse(t testing.TB, tlsResp arangodb.TLSDataResponse, operati // Test_ReloadTLSData tests TLS certificate reload functionality, skipping if superuser rights unavailable. func Test_ReloadTLSData(t *testing.T) { Wrap(t, func(t *testing.T, client arangodb.Client) { - withContextT(t, time.Minute, func(ctx context.Context, t testing.TB) { + withContextT(t, defaultTestTimeout, func(ctx context.Context, t testing.TB) { if !isNoAuth() { t.Skip("Skipping: superuser tests run only in no-auth mode (TEST_AUTH=none)") } @@ -397,7 +399,7 @@ func Test_ReloadTLSData(t *testing.T) { // The test is skipped if superuser rights are missing or the feature is disabled/not configured. func Test_RotateEncryptionAtRestKey(t *testing.T) { Wrap(t, func(t *testing.T, client arangodb.Client) { - withContextT(t, time.Minute, func(ctx context.Context, t testing.TB) { + withContextT(t, defaultTestTimeout, func(ctx context.Context, t testing.TB) { if !isNoAuth() { t.Skip("Skipping: superuser tests run only in no-auth mode (TEST_AUTH=none)") } @@ -464,7 +466,7 @@ func Test_GetJWTSecrets(t *testing.T) { // Test_ReloadJWTSecrets validates JWT secrets reload functionality, skipping if not available. func Test_ReloadJWTSecrets(t *testing.T) { Wrap(t, func(t *testing.T, client arangodb.Client) { - withContextT(t, time.Minute, func(ctx context.Context, t testing.TB) { + withContextT(t, defaultTestTimeout, func(ctx context.Context, t testing.TB) { resp, err := client.ReloadJWTSecrets(ctx) if err != nil { if handleJWTSecretsError(t, err, "ReloadJWTSecrets", []int{http.StatusForbidden, http.StatusBadRequest}) { @@ -528,7 +530,7 @@ func validateJWTSecretsResponse(t testing.TB, resp arangodb.JWTSecretsResult, op } func Test_HandleAdminVersion(t *testing.T) { Wrap(t, func(t *testing.T, client arangodb.Client) { - withContextT(t, time.Minute, func(ctx context.Context, tb testing.TB) { + withContextT(t, defaultTestTimeout, func(ctx context.Context, tb testing.TB) { t.Run("With Options", func(t *testing.T) { resp, err := client.HandleAdminVersion(context.Background(), &arangodb.GetVersionOptions{ Details: utils.NewType(true), @@ -554,7 +556,7 @@ func Test_HandleAdminVersion(t *testing.T) { func Test_GetDeploymentId(t *testing.T) { Wrap(t, func(t *testing.T, client arangodb.Client) { t.Run("Success case", func(t *testing.T) { - withContextT(t, time.Minute, func(ctx context.Context, t testing.TB) { + withContextT(t, defaultTestTimeout, func(ctx context.Context, t testing.TB) { version := skipBelowVersion(client, ctx, "3.12.6", t) t.Logf("Current Version %s", version.Version) @@ -568,7 +570,7 @@ func Test_GetDeploymentId(t *testing.T) { }) t.Run("Multiple calls consistency", func(t *testing.T) { - withContextT(t, time.Minute, func(ctx context.Context, t testing.TB) { + withContextT(t, defaultTestTimeout, func(ctx context.Context, t testing.TB) { version := skipBelowVersion(client, ctx, "3.12.6", t) t.Logf("Current Version %s", version.Version) diff --git a/v2/tests/asyncjob_test.go b/v2/tests/asyncjob_test.go index f8ecfe26..226da7d5 100644 --- a/v2/tests/asyncjob_test.go +++ b/v2/tests/asyncjob_test.go @@ -111,6 +111,8 @@ func TestAsyncJobListPending(t *testing.T) { skipBelowVersion(client, ctx, "3.11.1", t) skipResilientSingleMode(t) + requireV8Enabled(client, ctx, t) + ctxAsync := connection.WithAsync(context.Background()) idTransaction := runLongRequest(t, ctxAsync, db, 2, col.Name()) @@ -254,6 +256,7 @@ func TestAsyncJobDelete(t *testing.T) { }) t.Run("delete pending job", func(t *testing.T) { + requireV8Enabled(client, ctx, t) idTransaction := runLongRequest(t, ctxAsync, db, 10, col.Name()) require.NotEmpty(t, idTransaction) @@ -275,6 +278,7 @@ func TestAsyncJobDelete(t *testing.T) { }) t.Run("delete expired jobs", func(t *testing.T) { + requireV8Enabled(client, ctx, t) idTransaction := runLongRequest(t, ctxAsync, db, 10, col.Name()) require.NotEmpty(t, idTransaction) diff --git a/v2/tests/call_test.go b/v2/tests/call_test.go index 588327d7..0e60300c 100644 --- a/v2/tests/call_test.go +++ b/v2/tests/call_test.go @@ -87,7 +87,11 @@ func Test_CallWithChecks(t *testing.T) { ok, arangoErr := shared.IsArangoError(err) require.True(t, ok) require.True(t, arangoErr.HasError) - require.Equal(t, http.StatusNotFound, resp.Code()) + t.Logf("Response code: %d", resp.Code()) + require.True(t, + resp.Code() == http.StatusNotFound || + resp.Code() == http.StatusNotImplemented, + "expected status 404 or 501, got %d", resp.Code()) }) }) }) diff --git a/v2/tests/database_query_test.go b/v2/tests/database_query_test.go index fb4f80e6..42c89a32 100644 --- a/v2/tests/database_query_test.go +++ b/v2/tests/database_query_test.go @@ -1302,6 +1302,7 @@ func Test_UserDefinedFunctions(t *testing.T) { Wrap(t, func(t *testing.T, client arangodb.Client) { WithDatabase(t, client, nil, func(db arangodb.Database) { withContextT(t, defaultTestTimeout, func(ctx context.Context, tb testing.TB) { + requireV8Enabled(client, ctx, tb) // Define UDF details namespace := "myfunctions::temperature::" + StringWithCharset(16, charset) functionName := namespace + "::celsiustofahrenheit" diff --git a/v2/tests/database_transactionsjs_test.go b/v2/tests/database_transactionsjs_test.go index 9d9b19ff..ed112702 100644 --- a/v2/tests/database_transactionsjs_test.go +++ b/v2/tests/database_transactionsjs_test.go @@ -34,7 +34,7 @@ func Test_DatabaseTransactionsJS(t *testing.T) { Wrap(t, func(t *testing.T, client arangodb.Client) { WithDatabase(t, client, nil, func(db arangodb.Database) { WithCollectionV2(t, db, nil, func(col arangodb.Collection) { - + requireV8Enabled(client, context.Background(), t) t.Run("Transaction ReturnValue", func(t *testing.T) { withContextT(t, defaultTestTimeout, func(ctx context.Context, t testing.TB) { txJSOptions := arangodb.TransactionJSOptions{ diff --git a/v2/tests/foxx_test.go b/v2/tests/foxx_test.go index b7431e75..26cbb766 100644 --- a/v2/tests/foxx_test.go +++ b/v2/tests/foxx_test.go @@ -36,6 +36,7 @@ func Test_FoxxItzpapalotlService(t *testing.T) { Wrap(t, func(t *testing.T, client arangodb.Client) { WithDatabase(t, client, nil, func(db arangodb.Database) { withContextT(t, defaultTestTimeout, func(ctx context.Context, tb testing.TB) { + requireV8Enabled(client, ctx, tb) if os.Getenv("TEST_CONNECTION") == "vst" { skipBelowVersion(client, ctx, "3.6", t) } @@ -298,6 +299,7 @@ func Test_ListInstalledFoxxServices(t *testing.T) { Wrap(t, func(t *testing.T, client arangodb.Client) { WithDatabase(t, client, nil, func(db arangodb.Database) { withContextT(t, defaultTestTimeout, func(ctx context.Context, tb testing.TB) { + requireV8Enabled(client, ctx, tb) services, err := client.ListInstalledFoxxServices(ctx, db.Name(), nil) require.NoError(t, err) require.NotEmpty(t, services) @@ -325,6 +327,7 @@ func Test_GetInstalledFoxxService(t *testing.T) { Wrap(t, func(t *testing.T, client arangodb.Client) { WithDatabase(t, client, nil, func(db arangodb.Database) { withContextT(t, defaultTestTimeout, func(ctx context.Context, tb testing.TB) { + requireV8Enabled(client, ctx, tb) mount := "/_api/foxx" serviceDetails, err := client.GetInstalledFoxxService(ctx, db.Name(), &mount) require.NoError(t, err) diff --git a/v2/tests/tasks_test.go b/v2/tests/tasks_test.go index 6f6edb06..a52e65de 100644 --- a/v2/tests/tasks_test.go +++ b/v2/tests/tasks_test.go @@ -55,6 +55,7 @@ func Test_CreateNewTask(t *testing.T) { Wrap(t, func(t *testing.T, client arangodb.Client) { WithDatabase(t, client, nil, func(db arangodb.Database) { withContextT(t, defaultTestTimeout, func(ctx context.Context, tb testing.TB) { + requireV8Enabled(client, ctx, tb) testCases := map[string]*arangodb.TaskOptions{ "taskWithParams": { Name: utils.NewType("taskWithParams"), @@ -128,6 +129,7 @@ func Test_ValidationsForCreateNewTask(t *testing.T) { Wrap(t, func(t *testing.T, client arangodb.Client) { WithDatabase(t, client, nil, func(db arangodb.Database) { withContextT(t, defaultTestTimeout, func(ctx context.Context, tb testing.TB) { + requireV8Enabled(client, ctx, tb) testCases := map[string]*arangodb.TaskOptions{ "taskWithoutCommand": { Name: utils.NewType("taskWithoutCommand"), @@ -160,6 +162,7 @@ func Test_TaskCreationWithId(t *testing.T) { Wrap(t, func(t *testing.T, client arangodb.Client) { WithDatabase(t, client, nil, func(db arangodb.Database) { withContextT(t, defaultTestTimeout, func(ctx context.Context, tb testing.TB) { + requireV8Enabled(client, ctx, tb) taskID := "test-task-id" + StringWithCharset(16, charset) options := &arangodb.TaskOptions{ ID: &taskID, // Optional if CreateTaskWithID sets it, but safe to keep diff --git a/v2/tests/util_test.go b/v2/tests/util_test.go index 3450f3ee..241d52e4 100644 --- a/v2/tests/util_test.go +++ b/v2/tests/util_test.go @@ -29,6 +29,7 @@ import ( "github.com/stretchr/testify/require" "github.com/arangodb/go-driver/v2/arangodb" + "github.com/arangodb/go-driver/v2/utils" ) func getTestMode() string { @@ -136,3 +137,27 @@ func skipVersionNotInRange(c arangodb.Client, ctx context.Context, minVersion, m } return x } + +// requireV8Enabled skips the test if V8 is disabled in the ArangoDB server. +// V8 is required for features like tasks, UDFs, Foxx, JS transactions, and simple queries. +// This function checks the v8-version field in the version details. +// If v8-version is "none", V8 is disabled and the test will be skipped. +func requireV8Enabled(c arangodb.Client, ctx context.Context, t testing.TB) { + versionInfo, err := c.VersionWithOptions(ctx, &arangodb.GetVersionOptions{ + Details: utils.NewType(true), + }) + t.Logf("V8-Version %s", versionInfo.Details["v8-version"]) + if err != nil { + t.Fatalf("Failed to get version info with details: %s", err) + } + + // Check if v8-version exists in Details and if it's "none" + if versionInfo.Details != nil { + if v8Version, ok := versionInfo.Details["v8-version"]; ok { + if v8VersionStr, ok := v8Version.(string); ok && v8VersionStr == "none" { + t.Skip("Skipping test: V8 is disabled in this ArangoDB server (v8-version: none). " + + "This test requires V8 enabled.") + } + } + } +}