Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
86929ac
start implementing python driver implementation
dothebart Dec 8, 2025
585473b
fix install
dothebart Dec 8, 2025
1ae67e4
only loop till the first error occurs
dothebart Dec 8, 2025
343c23f
add option to loop eternal
dothebart Dec 8, 2025
6a6615c
add new container version
dothebart Dec 8, 2025
30a16a8
add python job
dothebart Dec 8, 2025
34d42ed
lint
dothebart Dec 8, 2025
8b2b00b
make the noise
dothebart Dec 8, 2025
11dcdf7
specify jwt and password
dothebart Dec 9, 2025
680e7fd
configure JWT
dothebart Dec 9, 2025
eaca4a7
add async driver tests
dothebart Dec 9, 2025
ac98cfa
also install async dependencies
dothebart Dec 9, 2025
8f69073
fix docker file
dothebart Dec 9, 2025
1de1ecc
fix docker file
dothebart Dec 9, 2025
c7a04e2
fix docker file
dothebart Dec 9, 2025
87af11a
forward
dothebart Dec 9, 2025
5a7be20
fix directory
dothebart Dec 9, 2025
9011fbd
add user
dothebart Dec 9, 2025
d7b4850
Fixing python-arango-async
apetenchea Dec 14, 2025
f6d1ca5
No need for --enterprise
apetenchea Dec 15, 2025
f3a9d93
switch to jwt-file
dothebart Dec 15, 2025
e8e27df
enable allure loading
dothebart Dec 15, 2025
79d1e25
add allure
dothebart Dec 15, 2025
297d484
add allure
dothebart Dec 15, 2025
09022a8
move options to the python tests
dothebart Dec 15, 2025
434e1f8
pass on the JWT secret, simplify & fix the arguments
dothebart Dec 15, 2025
e2fba99
one more place for switching to jwt key file
dothebart Dec 15, 2025
db1ef64
make sure testing.js knows the JWT-secret as well
dothebart Dec 15, 2025
6ba1c75
fix JWT, enable backu
dothebart Dec 15, 2025
e1f9351
add a test blacklist
dothebart Dec 15, 2025
0470199
allways disable them for now
dothebart Dec 15, 2025
6351f74
add location for the foxx service
dothebart Dec 15, 2025
3649141
fix setting of JWT
dothebart Dec 16, 2025
c06c9cc
adjust test to reality, don't use the requests module
dothebart Dec 16, 2025
3fcc252
no more root user in the connection with JWT
dothebart Dec 16, 2025
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
2 changes: 1 addition & 1 deletion .circleci/base_config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ parameters:
default: "arangodb/ubuntubuildarangodb-devel:18"
test-docker-image:
type: string
default: public.ecr.aws/b0b8h2r4/test-ubuntu:24.04-5edcfbf3
default: public.ecr.aws/b0b8h2r4/test-ubuntu:24.04-1acd2d06
# Unused here, but it will be forwarded from config and will cause errors if not defined
enterprise-branch:
type: string
Expand Down
17 changes: 17 additions & 0 deletions .circleci/build_test_image.yml
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,18 @@ jobs:
cat << parameters.arch >>-tag-js.txt
docker tag $image:latest-<< parameters.arch >> $image:$(cat << parameters.arch >>-tag-js.txt)-<< parameters.arch >>
docker push $image:$(cat << parameters.arch >>-tag-js.txt)-<< parameters.arch >>
- run:
name: Build python Docker Image
command: |
set -x
cd /home/circleci/project/scripts/docker
echo << parameters.image >>
image=<< parameters.image >>-python
/bin/sh build-image.sh $image << parameters.arch >> python-test
/bin/sh determine-tag.sh $image << parameters.arch >> | tee << parameters.arch >>-tag-python.txt
cat << parameters.arch >>-tag-python.txt
docker tag $image:latest-<< parameters.arch >> $image:$(cat << parameters.arch >>-tag-python.txt)-<< parameters.arch >>
docker push $image:$(cat << parameters.arch >>-tag-python.txt)-<< parameters.arch >>
- run:
name: Build java Docker Image
command: |
Expand Down Expand Up @@ -214,6 +226,11 @@ jobs:
command: |
cd scripts/docker/
./build-manifest.sh << parameters.image >>-js $(cat amd64-tag-js.txt)
- run:
name: Build python test container manifest
command: |
cd scripts/docker/
./build-manifest.sh << parameters.image >>-python $(cat amd64-tag-python.txt)
- run:
name: Build java test container manifest
command: |
Expand Down
2 changes: 1 addition & 1 deletion .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ parameters:
description: "Used to create new test docker images after changes to the test docker image build process."
test-docker-image:
type: string
default: public.ecr.aws/b0b8h2r4/test-ubuntu:24.04-5edcfbf3
default: public.ecr.aws/b0b8h2r4/test-ubuntu:24.04-1acd2d06
description: "Docker image to use for testing ArangoDB - only relevant when trying new test images"
build-docker-image:
type: string
Expand Down
134 changes: 11 additions & 123 deletions js/client/modules/@arangodb/testsuites/java.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ const _ = require('lodash');
const fs = require('fs');
const pu = require('@arangodb/testutils/process-utils');
const tu = require('@arangodb/testutils/test-utils');
const testRunnerBase = require('@arangodb/testutils/testrunner').testRunner;
const { runWithAllureReport } = require('@arangodb/testutils/testrunners');
const yaml = require('js-yaml');
const platform = require('internal').platform;
const time = require('internal').time;
Expand All @@ -66,128 +66,9 @@ const testPaths = {
};

// //////////////////////////////////////////////////////////////////////////////
// / @brief TEST: shell_http
// / @brief TEST: java_driver
// //////////////////////////////////////////////////////////////////////////////

class runWithAllureReport extends testRunnerBase {
getAllureResults(testResultsDir, results, status) {
let allResultJsons = {};
let topLevelContainers = [];
let allContainerJsons = {};
let containerRe = /-container.json/;
let resultRe = /-result.json/;
let resultFiles = fs.list(testResultsDir).filter(file => {
return file.match(resultRe) !== null;
});
if (resultFiles.length === 0) {
let msg = `did not find any files in ${testResultsDir}`;
print(msg);
results['status'] = false;
results['message'] = msg;
}
//print(resultFiles)
resultFiles.forEach(containerFile => {
let resultJson = JSON.parse(fs.read(fs.join(testResultsDir, containerFile)));
resultJson['parents'] = [];
allResultJsons[resultJson.uuid] = resultJson;
});

let containerFiles = fs.list(testResultsDir).filter(file => file.match(containerRe) !== null);
containerFiles.forEach(containerFile => {
let container = JSON.parse(fs.read(fs.join(testResultsDir, containerFile)));
container['childContainers'] = [];
container['isToplevel'] = false;
//print(container)
container.children.forEach(child => {
allResultJsons[child]['parents'].push(container.uuid);
});
allContainerJsons[container.uuid] = container;
});

for(let oneResultKey in allResultJsons) {
allResultJsons[oneResultKey].parents =
allResultJsons[oneResultKey].parents.sort(function(aUuid, bUuid) {
let a = allContainerJsons[aUuid];
let b = allContainerJsons[bUuid];
if ((a.start !== b.start) || (a.stop !== b.stop)) {
return (b.stop - b.start) - (a.stop - a.start);
}
if (a.children.length !== b.children.length) {
return b.children.length - a.children.length;
}
//print(a)
//print(b)
//print('--------')
return 0;
});
for (let i = 0; i + 1 < allResultJsons[oneResultKey].parents.length; i++) {
let parent = allResultJsons[oneResultKey].parents[i];
let child = allResultJsons[oneResultKey].parents[i + 1];
if(i === 0) {
topLevelContainers.push(parent);
}
if (!allContainerJsons[parent]['childContainers'].includes(child)) {
allContainerJsons[parent]['childContainers'].push(child);
}
// print(allContainerJsons[parent])
}
//print(allResultJsons[oneResultKey])
//print('vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv')
}
//print(topLevelContainers)
topLevelContainers.forEach(id => {
//print('zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz')
let tlContainer = allContainerJsons[id];
//print(tlContainer['childContainers'])

let resultSet = {
duration: tlContainer.stop - tlContainer.start,
total: tlContainer.children.length,
failed: 0,
status: true
};
results[tlContainer.name] = resultSet;

tlContainer['childContainers'].forEach(childContainerId => {
let childContainer = allContainerJsons[childContainerId];
let suiteResult = {};
resultSet[childContainer.name] = suiteResult;
//print(childContainer);
childContainer['childContainers'].forEach(grandChildContainerId => {
let grandChildContainer = allContainerJsons[grandChildContainerId];
//print(grandChildContainer);
let name = childContainer.name + "." + grandChildContainer.name;
if (grandChildContainer.children.length !== 1) {
print(RED+"This grandchild has more than one item - not supported!"+RESET);
print(RED+grandChildContainer.children+RESET);
}
let gcTestResult = allResultJsons[grandChildContainer.children[0]];
let message = "";
if (gcTestResult.hasOwnProperty('statusDetails')) {
message = gcTestResult.statusDetails.message + "\n\n" + gcTestResult.statusDetails.trace;
}
let myResult = {
duration: gcTestResult.stop - gcTestResult.start,
status: (gcTestResult.status === "passed") || (gcTestResult.status === "skipped"),
message: message
};

suiteResult[grandChildContainer.name + '.' + gcTestResult.name] = myResult;
if (!myResult.status) {
status = false;
suiteResult.status = false;
// suiteResult.message = myResult.message;
results.message += myResult.message;
}
});
});
//print('zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz')
});
results['timeout'] = false;
results['status'] = status;
}
}

class runInJavaTest extends runWithAllureReport {
constructor(options, testname, ...optionalArgs) {
let opts = _.clone(tu.testClientJwtAuthInfo);
Expand Down Expand Up @@ -226,7 +107,11 @@ arangodb.acquireHostList=true
fs.write(propertiesFileName, propertiesFileContent);
let args = [
'verify',
'-am',
];
if (this.options.loopEternal) {
args = args.concat(['-am',]);
}
args = args.concat([
'-pl',
'test-functional',
'-Dgpg.skip',
Expand All @@ -237,7 +122,7 @@ arangodb.acquireHostList=true
'-Dallure.results.directory=' + testResultsDir,
'-Dmaven.wagon.http.retryHandler.count=10',
// TODO? '-Dnative=<<parameters.native>>'
];
]);

if (this.options.testCase) {
args.push('-Dit.test=' + this.options.testCase);
Expand All @@ -248,6 +133,9 @@ arangodb.acquireHostList=true
args.push('-D' + key + '=' + this.options.javaOptions[key]);
}
}
if (this.options.loopEternal) {
args = ['failsafe:integration-test', 'failsafe:verify'].concat(args);
}
if (this.options.extremeVerbosity) {
print(args);
}
Expand Down
176 changes: 176 additions & 0 deletions js/client/modules/@arangodb/testsuites/python-arango.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,176 @@
/* jshint strict: false, sub: true */
/* global print, db, SYS_IS_V8_BUILD */
'use strict';

// //////////////////////////////////////////////////////////////////////////////
// / DISCLAIMER
// /
// / Copyright 2014-2024 ArangoDB GmbH, Cologne, Germany
// / Copyright 2004-2014 triAGENS GmbH, Cologne, Germany
// /
// / Licensed under the Business Source License 1.1 (the "License");
// / you may not use this file except in compliance with the License.
// / You may obtain a copy of the License at
// /
// / https://github.com/arangodb/arangodb/blob/devel/LICENSE
// /
// / 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.
// /
// / Copyright holder is ArangoDB GmbH, Cologne, Germany
// /
// / @author Wilfried Goesgens
// //////////////////////////////////////////////////////////////////////////////

const functionsDocumentation = {
'python_driver': 'python_arango client driver test',
};
const optionsDocumentation = [
' - `pythonsource`: directory of the java driver',
' - `pythonOptions`: additional arguments to pass via the commandline',
' can be found in arangodb-java-driver/src/test/java/utils/TestUtils.java',
];

const internal = require('internal');

const executeExternal = internal.executeExternal;
const executeExternalAndWait = internal.executeExternalAndWait;
const statusExternal = internal.statusExternal;

/* Modules: */
const _ = require('lodash');
const fs = require('fs');
const pu = require('@arangodb/testutils/process-utils');
const tu = require('@arangodb/testutils/test-utils');
const { runWithAllureReport } = require('@arangodb/testutils/testrunners');
const yaml = require('js-yaml');
const platform = require('internal').platform;
const time = require('internal').time;
const isEnterprise = require("@arangodb/test-helper").isEnterprise;

// const BLUE = require('internal').COLORS.COLOR_BLUE;
// const CYAN = require('internal').COLORS.COLOR_CYAN;
// const GREEN = require('internal').COLORS.COLOR_GREEN;
const RED = require('internal').COLORS.COLOR_RED;
const RESET = require('internal').COLORS.COLOR_RESET;
// const YELLOW = require('internal').COLORS.COLOR_YELLOW;

const testPaths = {
'python_driver': []
};

// //////////////////////////////////////////////////////////////////////////////
// / @brief TEST: shell_http
// //////////////////////////////////////////////////////////////////////////////

class runInPythonTest extends runWithAllureReport {
constructor(options, testname, ...optionalArgs) {
let opts = _.clone(options);
opts['password'] = 'pythonarango';
opts['username'] = 'root';
opts["encryptionAtRest"] = true;
opts.extraArgs = {
// needed by Python jwt tests, otherwise the returned token is "invalid", see RestAuthHandler.cpp:58
'server.authentication': 'true',
// need by Python tests to query the options API
'server.options-api': 'admin',
'backup.api-enabled': true,
};
//opts['arangodConfig'] = 'arangod-auth.conf';
_.defaults(opts, options);
super(opts, testname, ...optionalArgs);
this.info = "runInPythonTest";
}
checkSutCleannessBefore() {}
checkSutCleannessAfter() { return true; }
runOneTest(file) {
print(this.instanceManager.setPassvoid('pythonarango'));
let topology;
let testResultsDir = fs.join(this.instanceManager.rootDir, 'pythonresults');
let results = {
'message': ''
};

let args = [
'--root', 'root',
'--password', 'pythonarango',
'--secret', fs.read(this.instanceManager.restKeyFile),
'--junitxml', 'test-results/junit.xml',
'--log-cli-level', 'DEBUG',
'--host', '127.0.0.1',
'--port', `${this.instanceManager.endpointPort}`,
'--alluredir', testResultsDir,
// TODO: '--foxx-app-source', fs.join(this.options.pythonsource, '/tests/static'),
];

let testSkipList = [];
if (!this.options.cluster) {
testSkipList.push('backup');
}
if (true) { //!SYS_IS_V8_BUILD) {
testSkipList.push('foxx');
//testSkipList.push('tasks');
testSkipList.push('js-transactions');
}
if (testSkipList.length > 0) {
args = args.concat(['--skip'].concat(testSkipList));
}
if (this.options.cluster) {
args = args.concat([
'--cluster',
'--port', `${this.instanceManager.endpointPorts[1]}`,
'--port', `${this.instanceManager.endpointPorts[2]}`,
]);
}
if (this.options.testCase) {
args = args.concat(['-k', this.options.testCase]);
}
if (this.options.pythonOptions !== '') {
for (var key in this.options.pythonOptions) {
args.push('--' + key + '=' + this.options.pythonOptions[key]);
}
}
if (this.options.extremeVerbosity) {
print(args);
}
let start = Date();
let status = true;
const cwd = fs.normalize(fs.makeAbsolute(this.options.pythonsource));
const rc = executeExternalAndWait('pytest', args, false, 0, [], cwd);
if (rc.exit !== 0) {
status = false;
}
results = {
status: status,
failed: (status)?0:1,
};
print(results);
this.getAllureResults(testResultsDir, results, status);
return results;
}
}

function pythonDriver (options) {
let localOptions = Object.assign({}, options, tu.testServerAuthInfo);
if (localOptions.cluster && localOptions.dbServers < 3) {
localOptions.dbServers = 3;
localOptions.coordinators = 3;
}
let rc = new runInPythonTest(localOptions, 'python_test').run([ 'python_test.js']);
options.cleanup = options.cleanup && localOptions.cleanup;
return rc;
}

exports.setup = function (testFns, opts, fnDocs, optionsDoc, allTestPaths) {
Object.assign(allTestPaths, testPaths);
testFns['python_driver'] = pythonDriver;
tu.CopyIntoObject(fnDocs, functionsDocumentation);
tu.CopyIntoList(optionsDoc, optionsDocumentation);
tu.CopyIntoObject(opts, {
'pythonOptions': '',
'pythonsource': '../python-arango-async',
});
};
Loading