Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
3 changes: 3 additions & 0 deletions client_server_info.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@ type ClientServerInfo interface {
// ServerID Gets the ID of this server in the cluster.
// An error is returned when calling this to a server that is not part of a cluster.
ServerID(ctx context.Context) (string, error)

// VersionWithOptions returns version information from the connected database server.
VersionWithOptions(ctx context.Context, details bool) (VersionInfo, error)
}

// ServerRole is the role of an arangod server
Expand Down
28 changes: 28 additions & 0 deletions client_server_info_impl.go
Original file line number Diff line number Diff line change
Expand Up @@ -157,3 +157,31 @@ func (c *client) echo(ctx context.Context) error {
}
return nil
}

func (c *client) VersionWithOptions(ctx context.Context, details bool) (VersionInfo, error) {
path := "_api/version"
if details {
path = "_api/version?details=true"
}

req, err := c.conn.NewRequest("GET", path)
if err != nil {
return VersionInfo{}, WithStack(err)
}

applyContextSettings(ctx, req)

resp, err := c.conn.Do(ctx, req)
if err != nil {
return VersionInfo{}, WithStack(err)
}
if err := resp.CheckStatus(200); err != nil {
return VersionInfo{}, WithStack(err)
}

var data VersionInfo
if err := resp.ParseBody("", &data); err != nil {
return VersionInfo{}, WithStack(err)
}
return data, nil
}
9 changes: 9 additions & 0 deletions test/asyncjob_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,9 @@ func TestAsyncJobListPending(t *testing.T) {
EnsureVersion(t, ctx, c).CheckVersion(MinimumVersion("3.11.1"))
skipResilientSingle(t)

// for disabling v8 tests
requireV8Enabled(c, ctx, t)

db := ensureDatabase(ctx, c, databaseName("db", "async"), nil, t)
defer func() {
err := db.Remove(ctx)
Expand Down Expand Up @@ -254,6 +257,9 @@ func TestAsyncJobDelete(t *testing.T) {
})

t.Run("delete pending job", func(t *testing.T) {
// for disabling v8 tests
requireV8Enabled(c, ctx, t)

idTransaction := runLongRequest(t, ctxAsync, db, 10, col.Name())
require.NotEmpty(t, idTransaction)

Expand All @@ -275,6 +281,9 @@ func TestAsyncJobDelete(t *testing.T) {
})

t.Run("delete expired jobs", func(t *testing.T) {
// for disabling v8 tests
requireV8Enabled(c, ctx, t)

idTransaction := runLongRequest(t, ctxAsync, db, 10, col.Name())
require.NotEmpty(t, idTransaction)

Expand Down
22 changes: 22 additions & 0 deletions test/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -670,3 +670,25 @@ func checkDBAccess(ctx context.Context, conn driver.Connection, dbName, username

return nil
}

// 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 driver.Client, ctx context.Context, t testing.TB) {
versionInfo, err := c.VersionWithOptions(ctx, true)
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"
// Only access versionInfo.Details after confirming there's no error
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.")
}
}
}
}
3 changes: 3 additions & 0 deletions test/database_transaction_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,10 @@ import (

func TestDatabaseTransaction(t *testing.T) {
c := createClient(t, nil)
// Ensure minimum version 3.2 for JavaScript transaction support
skipBelowVersion(c, "3.2", t)
// Skip versions above 4.0 where V8 may be disabled (V8 is required for JS transactions)
requireV8Enabled(c, context.Background(), t)
db := ensureDatabase(nil, c, "transaction_test", nil, t)
defer func() {
err := db.Remove(nil)
Expand Down
1 change: 1 addition & 0 deletions v2/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
- Add endpoint to fetch deployment id
- Add ARM Support for V2 testcases
- Set TESTV2PARALLEL from 1 to 4
- Disabled V8 related testcases in V1 and V2

## [2.1.6](https://github.com/arangodb/go-driver/tree/v2.1.6) (2025-11-06)
- Add missing endpoints from replication
Expand Down
3 changes: 2 additions & 1 deletion v2/arangodb/client_admin.go
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
3 changes: 2 additions & 1 deletion v2/tests/admin_cluster_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
20 changes: 11 additions & 9 deletions v2/tests/admin_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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)
})
Expand All @@ -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
Expand Down Expand Up @@ -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)")
}
Expand Down Expand Up @@ -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)")
}
Expand All @@ -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)")
}
Expand Down Expand Up @@ -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}) {
Expand Down Expand Up @@ -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),
Expand All @@ -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)

Expand All @@ -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)

Expand Down
4 changes: 4 additions & 0 deletions v2/tests/asyncjob_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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())
Expand Down Expand Up @@ -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)

Expand All @@ -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)

Expand Down
6 changes: 5 additions & 1 deletion v2/tests/call_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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())
})
})
})
Expand Down
86 changes: 34 additions & 52 deletions v2/tests/client_replication_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -292,6 +292,24 @@ func Test_UpdateApplierConfig(t *testing.T) {
})
}

func logApplierState(t *testing.T, prefix string, state arangodb.ApplierState) {
if state.Running == nil ||
state.Phase == nil ||
state.Progress == nil ||
state.Progress.Message == nil ||
state.Progress.FailedConnects == nil {
return
}

t.Logf("%s:\n running=%v\n phase=%s\n message=%s\n failedConnects=%d",
prefix,
*state.Running,
*state.Phase,
*state.Progress.Message,
*state.Progress.FailedConnects,
)
}

func Test_ApplierStart(t *testing.T) {
Wrap(t, func(t *testing.T, client arangodb.Client) {
WithDatabase(t, client, nil, func(db arangodb.Database) {
Expand Down Expand Up @@ -323,40 +341,21 @@ func Test_ApplierStart(t *testing.T) {
resp, err := client.ApplierStart(ctx, db.Name(), utils.NewType(false), utils.NewType(batch.ID))
require.NoError(t, err)
require.NotNil(t, resp)
// Log useful debug info
t.Logf("Applier start:\n running=%v\n phase=%s\n message=%s\n failedConnects=%d",
*resp.State.Running,
*resp.State.Phase,
*resp.State.Progress.Message,
*resp.State.Progress.FailedConnects,
)

logApplierState(t, "Applier state", resp.State)
})
t.Run("Applier_State_with_query_params", func(t *testing.T) {
ctx := context.Background()

state, err := client.GetApplierState(ctx, db.Name(), utils.NewType(false))
resp, err := client.GetApplierState(ctx, db.Name(), utils.NewType(false))
require.NoError(t, err, "failed to get applier state")
require.NotNil(t, state.State)

// Log useful debug info
t.Logf("Applier state:\n running=%v\n phase=%s\n message=%s\n failedConnects=%d",
*state.State.Running,
*state.State.Phase,
*state.State.Progress.Message,
*state.State.Progress.FailedConnects,
)

logApplierState(t, "Applier state", resp.State)
})
t.Run("Applier Stop with query params", func(t *testing.T) {
resp, err := client.ApplierStop(ctx, db.Name(), utils.NewType(false))
require.NoError(t, err)
require.NotNil(t, resp)
// Log useful debug info
t.Logf("Applier stop:\n running=%v\n phase=%s\n message=%s\n failedConnects=%d",
*resp.State.Running,
*resp.State.Phase,
*resp.State.Progress.Message,
*resp.State.Progress.FailedConnects,
)

logApplierState(t, "Applier state", resp.State)
})
t.Run("Update applier config with out query params", func(t *testing.T) {
resp, err := client.UpdateApplierConfig(ctx, db.Name(), nil, arangodb.ApplierOptions{
Expand All @@ -373,43 +372,26 @@ func Test_ApplierStart(t *testing.T) {
resp, err := client.ApplierStart(ctx, db.Name(), nil, nil)
require.NoError(t, err)
require.NotNil(t, resp)
// Log useful debug info
t.Logf("Applier start:\n running=%v\n phase=%s\n message=%s\n failedConnects=%d",
*resp.State.Running,
*resp.State.Phase,
*resp.State.Progress.Message,
*resp.State.Progress.FailedConnects,
)

logApplierState(t, "Applier state", resp.State)
})
t.Run("Applier State with out query params", func(t *testing.T) {
ctx := context.Background()

state, err := client.GetApplierState(ctx, db.Name(), nil)
resp, err := client.GetApplierState(ctx, db.Name(), nil)
require.NoError(t, err, "failed to get applier state")
require.NotNil(t, state.State)

// Log useful debug info
t.Logf("Applier state:\n running=%v\n phase=%s\n message=%s\n failedConnects=%d",
*state.State.Running,
*state.State.Phase,
*state.State.Progress.Message,
*state.State.Progress.FailedConnects,
)

logApplierState(t, "Applier state", resp.State)
})
t.Run("Applier Stop with out query params", func(t *testing.T) {
resp, err := client.ApplierStop(ctx, db.Name(), nil)
require.NoError(t, err)
require.NotNil(t, resp)
// Log useful debug info
t.Logf("Applier stop:\n running=%v\n phase=%s\n message=%s\n failedConnects=%d",
*resp.State.Running,
*resp.State.Phase,
*resp.State.Progress.Message,
*resp.State.Progress.FailedConnects,
)

logApplierState(t, "Applier state", resp.State)
})
})
})
}, WrapOptions{
Parallel: utils.NewType(false),
})
}

Expand Down
Loading