mirror of https://gitee.com/bigwinds/arangodb
Merge branch 'foxx-pathes' of github.com:triAGENS/ArangoDB into foxx-pathes
This commit is contained in:
commit
bd2a698ab6
|
@ -7,6 +7,10 @@ v2.5.0 (XXXX-XX-XX)
|
||||||
v2.4.1 (XXXX-XX-XX)
|
v2.4.1 (XXXX-XX-XX)
|
||||||
-------------------
|
-------------------
|
||||||
|
|
||||||
|
* better diagnostics for arangoimp
|
||||||
|
|
||||||
|
* fixed invalid result of HTTP REST API method `/_admin/foxx/rescan`
|
||||||
|
|
||||||
* fixed possible segmentation fault when passing a Buffer object into a V8 function
|
* fixed possible segmentation fault when passing a Buffer object into a V8 function
|
||||||
as a parameter
|
as a parameter
|
||||||
|
|
||||||
|
|
|
@ -86,16 +86,16 @@ collection in the default database (*_system*). To specify a different database,
|
||||||
use the *--server.database* option when invoking _arangoimp_.
|
use the *--server.database* option when invoking _arangoimp_.
|
||||||
|
|
||||||
An _arangoimp_ import run will print out the final results on the command line.
|
An _arangoimp_ import run will print out the final results on the command line.
|
||||||
By default, it shows the number of documents created, the number of errors that
|
By default, it shows the number of documents created, the number of warnings or errors that
|
||||||
occurred on the server side, and the total number of input file lines/documents
|
occurred on the server side, and the total number of input file lines/documents
|
||||||
that it processed. Additionally, _arangoimp_ will print out details about errors
|
that it processed. Additionally, _arangoimp_ will print out details about warnings and errors
|
||||||
that happened on the server-side (if any).
|
that happened on the server-side (if any).
|
||||||
|
|
||||||
*Examples*
|
*Examples*
|
||||||
|
|
||||||
```js
|
```js
|
||||||
created: 2
|
created: 2
|
||||||
errors: 0
|
warnings/errors: 0
|
||||||
total: 2
|
total: 2
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
@ -447,6 +447,7 @@ SHELL_COMMON = \
|
||||||
@top_srcdir@/js/common/tests/shell-index.js \
|
@top_srcdir@/js/common/tests/shell-index.js \
|
||||||
@top_srcdir@/js/common/tests/shell-index-geo.js \
|
@top_srcdir@/js/common/tests/shell-index-geo.js \
|
||||||
@top_srcdir@/js/common/tests/shell-cap-constraint.js \
|
@top_srcdir@/js/common/tests/shell-cap-constraint.js \
|
||||||
|
@top_srcdir@/js/common/tests/shell-cap-constraint-timecritical.js \
|
||||||
@top_srcdir@/js/common/tests/shell-unique-constraint.js \
|
@top_srcdir@/js/common/tests/shell-unique-constraint.js \
|
||||||
@top_srcdir@/js/common/tests/shell-hash-index.js \
|
@top_srcdir@/js/common/tests/shell-hash-index.js \
|
||||||
@top_srcdir@/js/common/tests/shell-fulltext.js \
|
@top_srcdir@/js/common/tests/shell-fulltext.js \
|
||||||
|
|
|
@ -3,3 +3,4 @@
|
||||||
{"id": 3, "_from": "UnitTestsImportVertex/v9", "_to": "UnitTestsImportVertex/v4", "what": "v9->v4", "extra": "foo"}
|
{"id": 3, "_from": "UnitTestsImportVertex/v9", "_to": "UnitTestsImportVertex/v4", "what": "v9->v4", "extra": "foo"}
|
||||||
|
|
||||||
{"id": 4, "_from": "UnitTestsImportVertex/v12", "_to": "UnitTestsImportVertex/what"}
|
{"id": 4, "_from": "UnitTestsImportVertex/v12", "_to": "UnitTestsImportVertex/what"}
|
||||||
|
{"id": 5}
|
||||||
|
|
|
@ -153,8 +153,25 @@ void RestImportHandler::registerError (RestImportResult& result,
|
||||||
++result._numErrors;
|
++result._numErrors;
|
||||||
|
|
||||||
result._errors.push_back(errorMsg);
|
result._errors.push_back(errorMsg);
|
||||||
|
}
|
||||||
|
|
||||||
LOG_WARNING("%s", errorMsg.c_str());
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @brief construct an error message
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
std::string RestImportHandler::buildParseError (size_t i,
|
||||||
|
char const* lineStart) {
|
||||||
|
if (lineStart != nullptr) {
|
||||||
|
string part(lineStart);
|
||||||
|
if (part.size() > 255) {
|
||||||
|
// UTF-8 chars in string will be escaped so we can truncate it at any point
|
||||||
|
part = part.substr(0, 255) + "...";
|
||||||
|
}
|
||||||
|
|
||||||
|
return positionise(i) + "invalid JSON type (expecting object, probably parse error), offending context: " + part;
|
||||||
|
}
|
||||||
|
|
||||||
|
return positionise(i) + "invalid JSON type (expecting object, probably parse error)";
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -162,13 +179,25 @@ void RestImportHandler::registerError (RestImportResult& result,
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
int RestImportHandler::handleSingleDocument (RestImportTransaction& trx,
|
int RestImportHandler::handleSingleDocument (RestImportTransaction& trx,
|
||||||
|
char const* lineStart,
|
||||||
TRI_json_t const* json,
|
TRI_json_t const* json,
|
||||||
string& errorMsg,
|
string& errorMsg,
|
||||||
bool isEdgeCollection,
|
bool isEdgeCollection,
|
||||||
bool waitForSync,
|
bool waitForSync,
|
||||||
size_t i) {
|
size_t i) {
|
||||||
if (! TRI_IsObjectJson(json)) {
|
if (! TRI_IsObjectJson(json)) {
|
||||||
errorMsg = positionise(i) + "invalid JSON type (expecting array)";
|
if (json != nullptr) {
|
||||||
|
string part = JsonHelper::toString(json);
|
||||||
|
if (part.size() > 255) {
|
||||||
|
// UTF-8 chars in string will be escaped so we can truncate it at any point
|
||||||
|
part = part.substr(0, 255) + "...";
|
||||||
|
}
|
||||||
|
|
||||||
|
errorMsg = positionise(i) + "invalid JSON type (expecting object), offending document: " + part;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
errorMsg = buildParseError(i, lineStart);
|
||||||
|
}
|
||||||
|
|
||||||
return TRI_ERROR_ARANGO_DOCUMENT_TYPE_INVALID;
|
return TRI_ERROR_ARANGO_DOCUMENT_TYPE_INVALID;
|
||||||
}
|
}
|
||||||
|
@ -182,7 +211,13 @@ int RestImportHandler::handleSingleDocument (RestImportTransaction& trx,
|
||||||
char const* to = extractJsonStringValue(json, TRI_VOC_ATTRIBUTE_TO);
|
char const* to = extractJsonStringValue(json, TRI_VOC_ATTRIBUTE_TO);
|
||||||
|
|
||||||
if (from == nullptr || to == nullptr) {
|
if (from == nullptr || to == nullptr) {
|
||||||
errorMsg = positionise(i) + "missing '_from' or '_to' attribute";
|
string part = JsonHelper::toString(json);
|
||||||
|
if (part.size() > 255) {
|
||||||
|
// UTF-8 chars in string will be escaped so we can truncate it at any point
|
||||||
|
part = part.substr(0, 255) + "...";
|
||||||
|
}
|
||||||
|
|
||||||
|
errorMsg = positionise(i) + "missing '_from' or '_to' attribute, offending document: " + part;
|
||||||
|
|
||||||
return TRI_ERROR_ARANGO_INVALID_EDGE_ATTRIBUTE;
|
return TRI_ERROR_ARANGO_INVALID_EDGE_ATTRIBUTE;
|
||||||
}
|
}
|
||||||
|
@ -600,7 +635,7 @@ bool RestImportHandler::createFromJson (string const& type) {
|
||||||
|
|
||||||
while (ptr < end) {
|
while (ptr < end) {
|
||||||
char const c = *ptr;
|
char const c = *ptr;
|
||||||
if (c == '\r' || c == '\n' || c == '\t' || c == ' ') {
|
if (c == '\r' || c == '\n' || c == '\t' || c == '\b' || c == '\f' || c == ' ') {
|
||||||
ptr++;
|
ptr++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -657,7 +692,7 @@ bool RestImportHandler::createFromJson (string const& type) {
|
||||||
|
|
||||||
// trim whitespace at start of line
|
// trim whitespace at start of line
|
||||||
while (ptr < end &&
|
while (ptr < end &&
|
||||||
(*ptr == ' ' || *ptr == '\t' || *ptr == '\r')) {
|
(*ptr == ' ' || *ptr == '\t' || *ptr == '\r' || *ptr == '\b' || *ptr == '\f')) {
|
||||||
++ptr;
|
++ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -667,6 +702,7 @@ bool RestImportHandler::createFromJson (string const& type) {
|
||||||
|
|
||||||
// now find end of line
|
// now find end of line
|
||||||
char const* pos = strchr(ptr, '\n');
|
char const* pos = strchr(ptr, '\n');
|
||||||
|
char const* oldPtr = nullptr;
|
||||||
|
|
||||||
TRI_json_t* json = nullptr;
|
TRI_json_t* json = nullptr;
|
||||||
|
|
||||||
|
@ -680,18 +716,20 @@ bool RestImportHandler::createFromJson (string const& type) {
|
||||||
// non-empty line
|
// non-empty line
|
||||||
*(const_cast<char*>(pos)) = '\0';
|
*(const_cast<char*>(pos)) = '\0';
|
||||||
TRI_ASSERT(ptr != nullptr);
|
TRI_ASSERT(ptr != nullptr);
|
||||||
json = parseJsonLine(ptr);
|
oldPtr = ptr;
|
||||||
|
json = parseJsonLine(ptr, pos);
|
||||||
ptr = pos + 1;
|
ptr = pos + 1;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// last-line, non-empty
|
// last-line, non-empty
|
||||||
TRI_ASSERT(pos == nullptr);
|
TRI_ASSERT(pos == nullptr);
|
||||||
TRI_ASSERT(ptr != nullptr);
|
TRI_ASSERT(ptr != nullptr);
|
||||||
|
oldPtr = ptr;
|
||||||
json = parseJsonLine(ptr);
|
json = parseJsonLine(ptr);
|
||||||
ptr = end;
|
ptr = end;
|
||||||
}
|
}
|
||||||
|
|
||||||
res = handleSingleDocument(trx, json, errorMsg, isEdgeCollection, waitForSync, i);
|
res = handleSingleDocument(trx, oldPtr, json, errorMsg, isEdgeCollection, waitForSync, i);
|
||||||
|
|
||||||
if (json != nullptr) {
|
if (json != nullptr) {
|
||||||
TRI_FreeJson(TRI_UNKNOWN_MEM_ZONE, json);
|
TRI_FreeJson(TRI_UNKNOWN_MEM_ZONE, json);
|
||||||
|
@ -734,7 +772,7 @@ bool RestImportHandler::createFromJson (string const& type) {
|
||||||
for (size_t i = 0; i < n; ++i) {
|
for (size_t i = 0; i < n; ++i) {
|
||||||
TRI_json_t const* json = static_cast<TRI_json_t const*>(TRI_AtVector(&documents->_value._objects, i));
|
TRI_json_t const* json = static_cast<TRI_json_t const*>(TRI_AtVector(&documents->_value._objects, i));
|
||||||
|
|
||||||
res = handleSingleDocument(trx, json, errorMsg, isEdgeCollection, waitForSync, i + 1);
|
res = handleSingleDocument(trx, nullptr, json, errorMsg, isEdgeCollection, waitForSync, i + 1);
|
||||||
|
|
||||||
if (res == TRI_ERROR_NO_ERROR) {
|
if (res == TRI_ERROR_NO_ERROR) {
|
||||||
++result._numCreated;
|
++result._numCreated;
|
||||||
|
@ -1071,12 +1109,12 @@ bool RestImportHandler::createFromKeyValueList () {
|
||||||
|
|
||||||
// trim line
|
// trim line
|
||||||
while (lineStart < bodyEnd &&
|
while (lineStart < bodyEnd &&
|
||||||
(*lineStart == ' ' || *lineStart == '\t' || *lineStart == '\r' || *lineStart == '\n')) {
|
(*lineStart == ' ' || *lineStart == '\t' || *lineStart == '\r' || *lineStart == '\n' || *lineStart == '\b' || *lineStart == '\f')) {
|
||||||
++lineStart;
|
++lineStart;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (lineEnd > lineStart &&
|
while (lineEnd > lineStart &&
|
||||||
(*(lineEnd - 1) == ' ' || *(lineEnd - 1) == '\t' || *(lineEnd - 1) == '\r' || *(lineEnd - 1) == '\n')) {
|
(*(lineEnd - 1) == ' ' || *(lineEnd - 1) == '\t' || *(lineEnd - 1) == '\r' || *(lineEnd - 1) == '\n' || *(lineEnd - 1) == '\b' || *(lineEnd - 1) == '\f')) {
|
||||||
--lineEnd;
|
--lineEnd;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1084,7 +1122,6 @@ bool RestImportHandler::createFromKeyValueList () {
|
||||||
TRI_json_t* keys = parseJsonLine(lineStart, lineEnd);
|
TRI_json_t* keys = parseJsonLine(lineStart, lineEnd);
|
||||||
|
|
||||||
if (! checkKeys(keys)) {
|
if (! checkKeys(keys)) {
|
||||||
LOG_WARNING("no JSON string array found in first line");
|
|
||||||
generateError(HttpResponse::BAD,
|
generateError(HttpResponse::BAD,
|
||||||
TRI_ERROR_HTTP_BAD_PARAMETER,
|
TRI_ERROR_HTTP_BAD_PARAMETER,
|
||||||
"no JSON string array found in first line");
|
"no JSON string array found in first line");
|
||||||
|
@ -1146,12 +1183,12 @@ bool RestImportHandler::createFromKeyValueList () {
|
||||||
|
|
||||||
// trim line
|
// trim line
|
||||||
while (lineStart < bodyEnd &&
|
while (lineStart < bodyEnd &&
|
||||||
(*lineStart == ' ' || *lineStart == '\t' || *lineStart == '\r' || *lineStart == '\n')) {
|
(*lineStart == ' ' || *lineStart == '\t' || *lineStart == '\r' || *lineStart == '\n' || *lineStart == '\b' || *lineStart == '\f')) {
|
||||||
++lineStart;
|
++lineStart;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (lineEnd > lineStart &&
|
while (lineEnd > lineStart &&
|
||||||
(*(lineEnd - 1) == ' ' || *(lineEnd - 1) == '\t' || *(lineEnd - 1) == '\r' || *(lineEnd - 1) == '\n')) {
|
(*(lineEnd - 1) == ' ' || *(lineEnd - 1) == '\t' || *(lineEnd - 1) == '\r' || *(lineEnd - 1) == '\n' || *(lineEnd - 1) == '\b' || *(lineEnd - 1) == '\f')) {
|
||||||
--lineEnd;
|
--lineEnd;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1170,7 +1207,7 @@ bool RestImportHandler::createFromKeyValueList () {
|
||||||
TRI_FreeJson(TRI_UNKNOWN_MEM_ZONE, values);
|
TRI_FreeJson(TRI_UNKNOWN_MEM_ZONE, values);
|
||||||
|
|
||||||
if (json != nullptr) {
|
if (json != nullptr) {
|
||||||
res = handleSingleDocument(trx, json, errorMsg, isEdgeCollection, waitForSync, i);
|
res = handleSingleDocument(trx, lineStart, json, errorMsg, isEdgeCollection, waitForSync, i);
|
||||||
TRI_FreeJson(TRI_UNKNOWN_MEM_ZONE, json);
|
TRI_FreeJson(TRI_UNKNOWN_MEM_ZONE, json);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -1194,7 +1231,7 @@ bool RestImportHandler::createFromKeyValueList () {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
string errorMsg = positionise(i) + "no valid JSON data";
|
string errorMsg = buildParseError(i, lineStart);
|
||||||
registerError(result, errorMsg);
|
registerError(result, errorMsg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -128,11 +128,19 @@ namespace triagens {
|
||||||
void registerError (RestImportResult&,
|
void registerError (RestImportResult&,
|
||||||
std::string const&);
|
std::string const&);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @brief construct an error message
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
std::string buildParseError (size_t,
|
||||||
|
char const*);
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// @brief process a single JSON document
|
/// @brief process a single JSON document
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
int handleSingleDocument (RestImportTransaction&,
|
int handleSingleDocument (RestImportTransaction&,
|
||||||
|
char const*,
|
||||||
TRI_json_t const*,
|
TRI_json_t const*,
|
||||||
std::string&,
|
std::string&,
|
||||||
bool,
|
bool,
|
||||||
|
|
|
@ -708,10 +708,8 @@ namespace triagens {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TRI_json_t const* importResult;
|
|
||||||
|
|
||||||
// look up the "created" flag. This returns a pointer, not a copy
|
// look up the "created" flag. This returns a pointer, not a copy
|
||||||
importResult = TRI_LookupObjectJson(json, "created");
|
TRI_json_t const* importResult = TRI_LookupObjectJson(json, "created");
|
||||||
|
|
||||||
if (TRI_IsNumberJson(importResult)) {
|
if (TRI_IsNumberJson(importResult)) {
|
||||||
_numberOk += (size_t) importResult->_value._number;
|
_numberOk += (size_t) importResult->_value._number;
|
||||||
|
|
|
@ -411,7 +411,7 @@ int main (int argc, char* argv[]) {
|
||||||
// give information about import
|
// give information about import
|
||||||
if (ok) {
|
if (ok) {
|
||||||
cout << "created: " << ih.getImportedLines() << endl;
|
cout << "created: " << ih.getImportedLines() << endl;
|
||||||
cout << "errors: " << ih.getErrorLines() << endl;
|
cout << "warnings/errors: " << ih.getErrorLines() << endl;
|
||||||
cout << "total: " << ih.getReadLines() << endl;
|
cout << "total: " << ih.getReadLines() << endl;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
|
@ -44,124 +44,7 @@ var easyPostCallback = actions.easyPostCallback;
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// @brief fetches a FOXX application
|
/// @brief sets up a Foxx application
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
actions.defineHttp({
|
|
||||||
url : "_admin/foxx/fetch",
|
|
||||||
prefix : false,
|
|
||||||
|
|
||||||
callback : function (req, res) {
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
var safe = /^[0-9a-zA-Z_\-\.]+$/;
|
|
||||||
|
|
||||||
if (req.suffix.length !== 0) {
|
|
||||||
actions.resultBad(req, res, arangodb.ERROR_HTTP_BAD_PARAMETER);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var json = actions.getJsonBody(req, res, actions.HTTP_BAD);
|
|
||||||
|
|
||||||
if (json === undefined) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var serverFile = json.filename;
|
|
||||||
var realFile = fs.join(fs.getTempPath(), serverFile);
|
|
||||||
|
|
||||||
if (! fs.isFile(realFile)) {
|
|
||||||
actions.resultNotFound(req, res, arangodb.errors.ERROR_FILE_NOT_FOUND.code);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
var name = json.name;
|
|
||||||
var version = json.version;
|
|
||||||
|
|
||||||
if (! safe.test(name)) {
|
|
||||||
fs.remove(realFile);
|
|
||||||
throw "rejecting unsafe name '" + name + "'";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (! safe.test(version)) {
|
|
||||||
fs.remove(realFile);
|
|
||||||
throw "rejecting unsafe version '" + version + "'";
|
|
||||||
}
|
|
||||||
|
|
||||||
var appPath = module.appPath();
|
|
||||||
|
|
||||||
if (typeof appPath === "undefined") {
|
|
||||||
fs.remove(realFile);
|
|
||||||
throw "javascript.app-path not set, rejecting app loading";
|
|
||||||
}
|
|
||||||
|
|
||||||
var path = fs.join(appPath, name + "-" + version);
|
|
||||||
|
|
||||||
if (!fs.exists(path)) {
|
|
||||||
fs.makeDirectoryRecursive(path);
|
|
||||||
fs.unzipFile(realFile, path, false, true);
|
|
||||||
|
|
||||||
foxxManager.scanAppDirectory();
|
|
||||||
}
|
|
||||||
fs.remove(realFile);
|
|
||||||
|
|
||||||
var found = arangodb.db._collection("_aal").firstExample({
|
|
||||||
type: "app",
|
|
||||||
path: name + "-" + version
|
|
||||||
});
|
|
||||||
|
|
||||||
if (found !== null) {
|
|
||||||
found = found.app;
|
|
||||||
}
|
|
||||||
|
|
||||||
actions.resultOk(req, res, actions.HTTP_OK, { path: path, app: found });
|
|
||||||
}
|
|
||||||
catch (err) {
|
|
||||||
actions.resultException(req, res, err, undefined, false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
/// @brief mounts a FOXX application
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
actions.defineHttp({
|
|
||||||
url : "_admin/foxx/mount",
|
|
||||||
prefix : false,
|
|
||||||
|
|
||||||
callback: easyPostCallback({
|
|
||||||
body: true,
|
|
||||||
callback: function (body) {
|
|
||||||
var appId = body.appId;
|
|
||||||
var mount = body.mount;
|
|
||||||
var options = body.options || {};
|
|
||||||
|
|
||||||
return foxxManager.mount(appId, mount, options);
|
|
||||||
}
|
|
||||||
})
|
|
||||||
});
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
/// @brief rescans the FOXX application directory
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
actions.defineHttp({
|
|
||||||
url : "_admin/foxx/rescan",
|
|
||||||
prefix : false,
|
|
||||||
|
|
||||||
callback: easyPostCallback({
|
|
||||||
body: true,
|
|
||||||
callback: function () {
|
|
||||||
foxxManager.scanAppDirectory();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
})
|
|
||||||
});
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
/// @brief sets up a FOXX application
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
actions.defineHttp({
|
actions.defineHttp({
|
||||||
|
@ -179,7 +62,7 @@ actions.defineHttp({
|
||||||
});
|
});
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// @brief tears down a FOXX application
|
/// @brief tears down a Foxx application
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
actions.defineHttp({
|
actions.defineHttp({
|
||||||
|
@ -197,11 +80,31 @@ actions.defineHttp({
|
||||||
});
|
});
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// @brief unmounts a FOXX application
|
/// @brief installs a Foxx application
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
actions.defineHttp({
|
actions.defineHttp({
|
||||||
url : "_admin/foxx/unmount",
|
url : "_admin/foxx/install",
|
||||||
|
prefix : false,
|
||||||
|
|
||||||
|
callback: easyPostCallback({
|
||||||
|
body: true,
|
||||||
|
callback: function (body) {
|
||||||
|
var appInfo = body.appInfo;
|
||||||
|
var mount = body.mount;
|
||||||
|
var options = body.options;
|
||||||
|
|
||||||
|
return foxxManager.install(appInfo, mount, options);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @brief uninstalls a Foxx application
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
actions.defineHttp({
|
||||||
|
url : "_admin/foxx/uninstall",
|
||||||
prefix : false,
|
prefix : false,
|
||||||
|
|
||||||
callback: easyPostCallback({
|
callback: easyPostCallback({
|
||||||
|
@ -209,85 +112,51 @@ actions.defineHttp({
|
||||||
callback: function (body) {
|
callback: function (body) {
|
||||||
var mount = body.mount;
|
var mount = body.mount;
|
||||||
|
|
||||||
return foxxManager.unmount(mount);
|
return foxxManager.uninstall(mount);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// @brief sets up a FOXX dev application
|
/// @brief replaces a Foxx application
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
actions.defineHttp({
|
actions.defineHttp({
|
||||||
url : "_admin/foxx/dev-setup",
|
url : "_admin/foxx/replace",
|
||||||
prefix : false,
|
prefix : false,
|
||||||
|
|
||||||
callback: easyPostCallback({
|
callback: easyPostCallback({
|
||||||
body: true,
|
body: true,
|
||||||
callback: function (body) {
|
callback: function (body) {
|
||||||
var name = body.name;
|
var appInfo = body.appInfo;
|
||||||
|
var mount = body.mount;
|
||||||
|
var options = body.options;
|
||||||
|
|
||||||
return foxxManager.devSetup(name);
|
return foxxManager.replace(appInfo, mount, options);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// @brief tears down a FOXX dev application
|
/// @brief upgrades a Foxx application
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
actions.defineHttp({
|
actions.defineHttp({
|
||||||
url : "_admin/foxx/dev-teardown",
|
url : "_admin/foxx/upgrade",
|
||||||
prefix : false,
|
prefix : false,
|
||||||
|
|
||||||
callback: easyPostCallback({
|
callback: easyPostCallback({
|
||||||
body: true,
|
body: true,
|
||||||
callback: function (body) {
|
callback: function (body) {
|
||||||
var name = body.name;
|
var appInfo = body.appInfo;
|
||||||
|
var mount = body.mount;
|
||||||
|
var options = body.options;
|
||||||
|
|
||||||
return foxxManager.devTeardown(name);
|
return foxxManager.upgrade(appInfo, mount, options);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
/// @brief purges a FOXX application
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
actions.defineHttp({
|
|
||||||
url : "_admin/foxx/purge",
|
|
||||||
prefix : false,
|
|
||||||
|
|
||||||
callback: easyPostCallback({
|
|
||||||
body: true,
|
|
||||||
callback: function (body) {
|
|
||||||
var name = body.name;
|
|
||||||
|
|
||||||
return foxxManager.purge(name);
|
|
||||||
}
|
|
||||||
})
|
|
||||||
});
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
/// @brief returns directory information
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
actions.defineHttp({
|
|
||||||
url : "_admin/foxx/config",
|
|
||||||
prefix : false,
|
|
||||||
|
|
||||||
callback : function (req, res) {
|
|
||||||
var result = {
|
|
||||||
appPath: module.appPath(),
|
|
||||||
devAppPath: internal.developmentMode ? module.devAppPath() : null,
|
|
||||||
logFilePath: internal.logfilePath,
|
|
||||||
startupPath: module.startupPath()
|
|
||||||
};
|
|
||||||
|
|
||||||
actions.resultOk(req, res, actions.HTTP_OK, { result: result });
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
// --SECTION-- END-OF-FILE
|
// --SECTION-- END-OF-FILE
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
ArangoError = require('org/arangodb').ArangoError,
|
ArangoError = require('org/arangodb').ArangoError,
|
||||||
<%= repository %> = require('<%= repositoryPath %>').Repository,
|
<%= repository %> = require('<%= repositoryPath %>').Repository,
|
||||||
<%= model %> = require('<%= modelPath %>').Model,
|
<%= model %> = require('<%= modelPath %>').Model,
|
||||||
|
joi = require('joi'),
|
||||||
_ = require('underscore'),
|
_ = require('underscore'),
|
||||||
controller,
|
controller,
|
||||||
<%= repositoryInstance %>;
|
<%= repositoryInstance %>;
|
||||||
|
@ -34,6 +35,18 @@
|
||||||
res.json(<%= repositoryInstance %>.save(<%= modelInstance %>).forClient());
|
res.json(<%= repositoryInstance %>.save(<%= modelInstance %>).forClient());
|
||||||
}).bodyParam('<%= modelInstance %>', 'The <%= model %> you want to create', <%= model %>);
|
}).bodyParam('<%= modelInstance %>', 'The <%= model %> you want to create', <%= model %>);
|
||||||
|
|
||||||
|
/** Reads a <%= model %>
|
||||||
|
*
|
||||||
|
* Reads a <%= model %>-Item.
|
||||||
|
*/
|
||||||
|
controller.get('/<%= basePath %>/:id', function (req, res) {
|
||||||
|
var id = req.params('id');
|
||||||
|
res.json(<%= repositoryInstance %>.byId(id).forClient());
|
||||||
|
}).pathParam('id', {
|
||||||
|
description: 'The id of the <%= model %>-Item',
|
||||||
|
type: 'string'
|
||||||
|
});
|
||||||
|
|
||||||
/** Updates a <%= model %>
|
/** Updates a <%= model %>
|
||||||
*
|
*
|
||||||
* Changes a <%= model %>-Item. The information has to be in the
|
* Changes a <%= model %>-Item. The information has to be in the
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1367,16 +1367,9 @@ function require (path) {
|
||||||
/// @brief createApp
|
/// @brief createApp
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
Module.prototype.createApp = function (description, options) {
|
Module.prototype.createApp = function (config) {
|
||||||
'use strict';
|
'use strict';
|
||||||
|
return new ArangoApp(config);
|
||||||
return new ArangoApp(
|
|
||||||
description.id,
|
|
||||||
description.manifest,
|
|
||||||
description.root,
|
|
||||||
description.path,
|
|
||||||
options
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
@ -1391,16 +1384,18 @@ function require (path) {
|
||||||
/// @brief ArangoApp constructor
|
/// @brief ArangoApp constructor
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
ArangoApp = function (id, manifest, root, path, options) {
|
ArangoApp = function (config) {
|
||||||
'use strict';
|
'use strict';
|
||||||
|
this._id = config.id; // ???
|
||||||
this._id = id;
|
this._manifest = config.manifest;
|
||||||
this._manifest = manifest;
|
this._name = config.manifest.name;
|
||||||
this._name = manifest.name;
|
this._version = config.manifest.version;
|
||||||
this._version = manifest.version;
|
this._root = config.root;
|
||||||
this._root = root;
|
this._path = config.path;
|
||||||
this._path = path;
|
this._options = config.options;
|
||||||
this._options = options;
|
this._mount = config.mount;
|
||||||
|
this._isSystem = config.isSystem || false;
|
||||||
|
this._isDevelopment = config.isDevelopment || false;
|
||||||
this._exports = {};
|
this._exports = {};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1428,6 +1423,35 @@ function require (path) {
|
||||||
// --SECTION-- public methods
|
// --SECTION-- public methods
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @brief creates a Json representation of itself to be persisted
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
ArangoApp.prototype.toJSON = function () {
|
||||||
|
var json = {
|
||||||
|
id: this._id,
|
||||||
|
manifest: this._manifest,
|
||||||
|
name: this._name,
|
||||||
|
version: this._version,
|
||||||
|
root: this._root,
|
||||||
|
path: this._path,
|
||||||
|
options: this._options,
|
||||||
|
mount: this._mount,
|
||||||
|
isSystem: this._isSystem,
|
||||||
|
isDevelopment: this._isDevelopment
|
||||||
|
};
|
||||||
|
if (this._manifest.hasOwnProperty("author")) {
|
||||||
|
json.author = this._manifest.author;
|
||||||
|
}
|
||||||
|
if (this._manifest.hasOwnProperty("description")) {
|
||||||
|
json.description = this._manifest.description;
|
||||||
|
}
|
||||||
|
if (this._manifest.hasOwnProperty("thumbnail")) {
|
||||||
|
json.thumbnail = this._manifest.thumbnail;
|
||||||
|
}
|
||||||
|
|
||||||
|
return json;
|
||||||
|
};
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// @brief createAppModule
|
/// @brief createAppModule
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
|
@ -39,6 +39,31 @@ var throwDownloadError = arangodb.throwDownloadError;
|
||||||
var errors = arangodb.errors;
|
var errors = arangodb.errors;
|
||||||
var ArangoError = arangodb.ArangoError;
|
var ArangoError = arangodb.ArangoError;
|
||||||
|
|
||||||
|
// TODO Only temporary
|
||||||
|
var tmp_getStorage = function() {
|
||||||
|
var c = db._tmp_aal;
|
||||||
|
if (c === undefined) {
|
||||||
|
c = db._create("_tmp_aal", {isSystem: true});
|
||||||
|
c.ensureUniqueConstraint("mount");
|
||||||
|
}
|
||||||
|
return c;
|
||||||
|
};
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @brief comparator for mount points
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
var compareMounts = function(l, r) {
|
||||||
|
var left = l.mount.toLowerCase();
|
||||||
|
var right = r.mount.toLowerCase();
|
||||||
|
|
||||||
|
if (left < right) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// @brief builds a github repository URL
|
/// @brief builds a github repository URL
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -248,31 +273,34 @@ function getStorage () {
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// @brief returns all installed FOXX applications
|
/// @brief returns all running Foxx applications
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
function listJson (showPrefix) {
|
function listJson (showPrefix, onlyDevelopment) {
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
var aal = getStorage();
|
var mounts = tmp_getStorage();
|
||||||
var cursor = aal.byExample({ type: "mount" });
|
var cursor;
|
||||||
|
if (onlyDevelopment) {
|
||||||
|
cursor = mounts.byExample({isDevelopment: true});
|
||||||
|
} else {
|
||||||
|
cursor = mounts.all();
|
||||||
|
}
|
||||||
var result = [];
|
var result = [];
|
||||||
|
var doc, res;
|
||||||
|
|
||||||
while (cursor.hasNext()) {
|
while (cursor.hasNext()) {
|
||||||
var doc = cursor.next();
|
doc = cursor.next();
|
||||||
|
|
||||||
var version = doc.app.replace(/^.+:(\d+(\.\d+)*)$/g, "$1");
|
res = {
|
||||||
|
|
||||||
var res = {
|
|
||||||
mountId: doc._key,
|
mountId: doc._key,
|
||||||
mount: doc.mount,
|
mount: doc.mount,
|
||||||
appId: doc.app,
|
|
||||||
name: doc.name,
|
name: doc.name,
|
||||||
description: doc.description,
|
description: doc.manifest.description,
|
||||||
author: doc.author,
|
author: doc.manifest.author,
|
||||||
system: doc.isSystem ? "yes" : "no",
|
system: doc.isSystem ? "yes" : "no",
|
||||||
active: doc.active ? "yes" : "no",
|
development: doc.isDevelopment ? "yes" : "no",
|
||||||
version: version
|
version: doc.version
|
||||||
};
|
};
|
||||||
|
|
||||||
if (showPrefix) {
|
if (showPrefix) {
|
||||||
|
@ -285,6 +313,52 @@ function listJson (showPrefix) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @brief prints all running Foxx applications
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
function list(onlyDevelopment) {
|
||||||
|
var apps = listJson(undefined, onlyDevelopment);
|
||||||
|
|
||||||
|
arangodb.printTable(
|
||||||
|
apps.sort(compareMounts),
|
||||||
|
[ "mount", "name", "author", "description", "version", "development" ],
|
||||||
|
{
|
||||||
|
prettyStrings: true,
|
||||||
|
totalString: "%s application(s) found",
|
||||||
|
emptyString: "no applications found",
|
||||||
|
rename: {
|
||||||
|
"mount": "Mount",
|
||||||
|
"name" : "Name",
|
||||||
|
"author" : "Author",
|
||||||
|
"description" : "Description",
|
||||||
|
"version" : "Version",
|
||||||
|
"development" : "Development"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @brief returns all running Foxx applications in development mode
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
function listDevelopmentJson (showPrefix) {
|
||||||
|
'use strict';
|
||||||
|
return listJson(showPrefix, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @brief prints all running Foxx applications
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
function listDevelopment() {
|
||||||
|
'use strict';
|
||||||
|
return list(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// @brief validate an app name and fail if it is invalid
|
/// @brief validate an app name and fail if it is invalid
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -302,19 +376,28 @@ function validateAppName (name) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function mountedApp (mount) {
|
||||||
|
"use strict";
|
||||||
|
return tmp_getStorage().firstExample({mount: mount});
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// @brief Exports
|
/// @brief Exports
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
exports.mountedApp = mountedApp;
|
||||||
|
exports.list = list;
|
||||||
exports.listJson = listJson;
|
exports.listJson = listJson;
|
||||||
|
exports.listDevelopment = listDevelopment;
|
||||||
|
exports.listDevelopmentJson = listDevelopmentJson;
|
||||||
exports.buildGithubUrl = buildGithubUrl;
|
exports.buildGithubUrl = buildGithubUrl;
|
||||||
exports.repackZipFile = repackZipFile;
|
exports.repackZipFile = repackZipFile;
|
||||||
exports.processDirectory = processDirectory;
|
exports.processDirectory = processDirectory;
|
||||||
exports.processGithubRepository = processGithubRepository;
|
exports.processGithubRepository = processGithubRepository;
|
||||||
exports.validateAppName = validateAppName;
|
exports.validateAppName = validateAppName;
|
||||||
|
|
||||||
|
exports.tmp_getStorage = tmp_getStorage;
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
// --SECTION-- END-OF-FILE
|
// --SECTION-- END-OF-FILE
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
|
@ -70,7 +70,7 @@ exports.Helper = {
|
||||||
else if (iterations === 400) {
|
else if (iterations === 400) {
|
||||||
require("console").log("waited very long for unload of collection " + collection.name());
|
require("console").log("waited very long for unload of collection " + collection.name());
|
||||||
}
|
}
|
||||||
else if (iterations === 800) {
|
else if (iterations === 1600) {
|
||||||
throw "waited too long for unload of collection " + collection.name();
|
throw "waited too long for unload of collection " + collection.name();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,192 @@
|
||||||
|
/*global require, db, assertEqual, assertTrue, ArangoCollection */
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @brief test the cap constraint
|
||||||
|
///
|
||||||
|
/// @file
|
||||||
|
///
|
||||||
|
/// DISCLAIMER
|
||||||
|
///
|
||||||
|
/// Copyright 2010-2012 triagens GmbH, Cologne, Germany
|
||||||
|
///
|
||||||
|
/// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
/// 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
|
||||||
|
///
|
||||||
|
/// 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 triAGENS GmbH, Cologne, Germany
|
||||||
|
///
|
||||||
|
/// @author Dr. Frank Celler, Lucas Dohmen
|
||||||
|
/// @author Copyright 2012, triAGENS GmbH, Cologne, Germany
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
var jsunity = require("jsunity");
|
||||||
|
var internal = require("internal");
|
||||||
|
var testHelper = require("org/arangodb/test-helper").Helper;
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
// --SECTION-- basic methods
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @brief test suite: Creation
|
||||||
|
/// these tests seem to fail when run in cluster or with valgrind from arangosh
|
||||||
|
/// (while they succeed when run on the frontend)
|
||||||
|
/// test-helper.js:Helper.waitUnload expects timeley behaviour
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
function CapConstraintTimecriticalSuite() {
|
||||||
|
var ERRORS = internal.errors;
|
||||||
|
var cn = "UnitTestsCollectionCap";
|
||||||
|
var collection = null;
|
||||||
|
|
||||||
|
var nsort = function (l, r) {
|
||||||
|
if (l !== r) {
|
||||||
|
return (l < r) ? -1 : 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
var assertBadParameter = function (err) {
|
||||||
|
assertTrue(err.errorNum === ERRORS.ERROR_BAD_PARAMETER.code ||
|
||||||
|
err.errorNum === ERRORS.ERROR_HTTP_BAD_PARAMETER.code);
|
||||||
|
};
|
||||||
|
|
||||||
|
return {
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @brief set up
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
setUp : function () {
|
||||||
|
internal.db._drop(cn);
|
||||||
|
collection = internal.db._create(cn);
|
||||||
|
},
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @brief tear down
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
tearDown : function () {
|
||||||
|
if (collection !== null) {
|
||||||
|
internal.wait(0);
|
||||||
|
collection.unload();
|
||||||
|
collection.drop();
|
||||||
|
collection = null;
|
||||||
|
}
|
||||||
|
internal.wait(0.0);
|
||||||
|
},
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @brief test: reload
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
testReload : function () {
|
||||||
|
var idx = collection.ensureCapConstraint(5);
|
||||||
|
var fun = function(d) { return d.n; };
|
||||||
|
|
||||||
|
assertEqual("cap", idx.type);
|
||||||
|
assertEqual(true, idx.isNewlyCreated);
|
||||||
|
assertEqual(5, idx.size);
|
||||||
|
assertEqual(0, idx.byteSize);
|
||||||
|
|
||||||
|
assertEqual(0, collection.count());
|
||||||
|
|
||||||
|
for (var i = 0; i < 10; ++i) {
|
||||||
|
collection.save({ n : i });
|
||||||
|
}
|
||||||
|
|
||||||
|
assertEqual(5, collection.count());
|
||||||
|
assertEqual([5, 6, 7, 8, 9], collection.toArray().map(fun).sort(nsort));
|
||||||
|
|
||||||
|
testHelper.waitUnload(collection, true);
|
||||||
|
|
||||||
|
assertEqual(5, collection.count());
|
||||||
|
assertEqual([5, 6, 7, 8, 9], collection.toArray().map(fun).sort(nsort));
|
||||||
|
|
||||||
|
collection.save({ n : 10 });
|
||||||
|
assertEqual(5, collection.count());
|
||||||
|
assertEqual([6, 7, 8, 9, 10], collection.toArray().map(fun).sort(nsort));
|
||||||
|
|
||||||
|
collection.save({ n : 11 });
|
||||||
|
assertEqual(5, collection.count());
|
||||||
|
assertEqual([7, 8, 9, 10, 11], collection.toArray().map(fun).sort(nsort));
|
||||||
|
|
||||||
|
testHelper.waitUnload(collection, true);
|
||||||
|
|
||||||
|
assertEqual(5, collection.count());
|
||||||
|
assertEqual([7, 8, 9, 10, 11], collection.toArray().map(fun).sort(nsort));
|
||||||
|
|
||||||
|
for (var i = 15; i < 20; ++i) {
|
||||||
|
collection.save({ n : i });
|
||||||
|
}
|
||||||
|
|
||||||
|
assertEqual(5, collection.count());
|
||||||
|
assertEqual([15, 16, 17, 18, 19], collection.toArray().map(fun).sort(nsort));
|
||||||
|
},
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @brief test: reload
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
testReloadMulti : function () {
|
||||||
|
var idx = collection.ensureCapConstraint(5);
|
||||||
|
var fun = function(d) { return d.n; };
|
||||||
|
|
||||||
|
assertEqual("cap", idx.type);
|
||||||
|
assertEqual(true, idx.isNewlyCreated);
|
||||||
|
assertEqual(5, idx.size);
|
||||||
|
assertEqual(0, idx.byteSize);
|
||||||
|
|
||||||
|
assertEqual(0, collection.count());
|
||||||
|
|
||||||
|
testHelper.waitUnload(collection, true);
|
||||||
|
|
||||||
|
assertEqual(0, collection.count());
|
||||||
|
|
||||||
|
for (var i = 0; i < 10; ++i) {
|
||||||
|
collection.save({ n : i });
|
||||||
|
}
|
||||||
|
|
||||||
|
testHelper.waitUnload(collection, true);
|
||||||
|
|
||||||
|
assertEqual(5, collection.count());
|
||||||
|
assertEqual([5, 6, 7, 8, 9], collection.toArray().map(fun).sort(nsort));
|
||||||
|
|
||||||
|
collection.save({ n : 10 });
|
||||||
|
|
||||||
|
testHelper.waitUnload(collection, true);
|
||||||
|
|
||||||
|
assertEqual(5, collection.count());
|
||||||
|
assertEqual([6, 7, 8, 9, 10], collection.toArray().map(fun).sort(nsort));
|
||||||
|
|
||||||
|
collection.save({ n: 0 });
|
||||||
|
assertEqual([0, 7, 8, 9, 10], collection.toArray().map(fun).sort(nsort));
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
// --SECTION-- main
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @brief executes the test suites
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
jsunity.run(CapConstraintTimecriticalSuite);
|
||||||
|
|
||||||
|
return jsunity.done();
|
||||||
|
|
||||||
|
// Local Variables:
|
||||||
|
// mode: outline-minor
|
||||||
|
// outline-regexp: "^\\(/// @brief\\|/// @addtogroup\\|// --SECTION--\\|/// @page\\|/// @}\\)"
|
||||||
|
// End:
|
|
@ -398,93 +398,6 @@ function CapConstraintSuite() {
|
||||||
assertEqual([ "abc", "def", "ghi" ], collection.toArray().map(fun).sort());
|
assertEqual([ "abc", "def", "ghi" ], collection.toArray().map(fun).sort());
|
||||||
},
|
},
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
/// @brief test: reload
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
testReload : function () {
|
|
||||||
var idx = collection.ensureCapConstraint(5);
|
|
||||||
var fun = function(d) { return d.n; };
|
|
||||||
|
|
||||||
assertEqual("cap", idx.type);
|
|
||||||
assertEqual(true, idx.isNewlyCreated);
|
|
||||||
assertEqual(5, idx.size);
|
|
||||||
assertEqual(0, idx.byteSize);
|
|
||||||
|
|
||||||
assertEqual(0, collection.count());
|
|
||||||
|
|
||||||
for (var i = 0; i < 10; ++i) {
|
|
||||||
collection.save({ n : i });
|
|
||||||
}
|
|
||||||
|
|
||||||
assertEqual(5, collection.count());
|
|
||||||
assertEqual([5, 6, 7, 8, 9], collection.toArray().map(fun).sort(nsort));
|
|
||||||
|
|
||||||
testHelper.waitUnload(collection, true);
|
|
||||||
|
|
||||||
assertEqual(5, collection.count());
|
|
||||||
assertEqual([5, 6, 7, 8, 9], collection.toArray().map(fun).sort(nsort));
|
|
||||||
|
|
||||||
collection.save({ n : 10 });
|
|
||||||
assertEqual(5, collection.count());
|
|
||||||
assertEqual([6, 7, 8, 9, 10], collection.toArray().map(fun).sort(nsort));
|
|
||||||
|
|
||||||
collection.save({ n : 11 });
|
|
||||||
assertEqual(5, collection.count());
|
|
||||||
assertEqual([7, 8, 9, 10, 11], collection.toArray().map(fun).sort(nsort));
|
|
||||||
|
|
||||||
testHelper.waitUnload(collection, true);
|
|
||||||
|
|
||||||
assertEqual(5, collection.count());
|
|
||||||
assertEqual([7, 8, 9, 10, 11], collection.toArray().map(fun).sort(nsort));
|
|
||||||
|
|
||||||
for (var i = 15; i < 20; ++i) {
|
|
||||||
collection.save({ n : i });
|
|
||||||
}
|
|
||||||
|
|
||||||
assertEqual(5, collection.count());
|
|
||||||
assertEqual([15, 16, 17, 18, 19], collection.toArray().map(fun).sort(nsort));
|
|
||||||
},
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
/// @brief test: reload
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
testReloadMulti : function () {
|
|
||||||
var idx = collection.ensureCapConstraint(5);
|
|
||||||
var fun = function(d) { return d.n; };
|
|
||||||
|
|
||||||
assertEqual("cap", idx.type);
|
|
||||||
assertEqual(true, idx.isNewlyCreated);
|
|
||||||
assertEqual(5, idx.size);
|
|
||||||
assertEqual(0, idx.byteSize);
|
|
||||||
|
|
||||||
assertEqual(0, collection.count());
|
|
||||||
|
|
||||||
testHelper.waitUnload(collection, true);
|
|
||||||
|
|
||||||
assertEqual(0, collection.count());
|
|
||||||
|
|
||||||
for (var i = 0; i < 10; ++i) {
|
|
||||||
collection.save({ n : i });
|
|
||||||
}
|
|
||||||
|
|
||||||
testHelper.waitUnload(collection, true);
|
|
||||||
|
|
||||||
assertEqual(5, collection.count());
|
|
||||||
assertEqual([5, 6, 7, 8, 9], collection.toArray().map(fun).sort(nsort));
|
|
||||||
|
|
||||||
collection.save({ n : 10 });
|
|
||||||
|
|
||||||
testHelper.waitUnload(collection, true);
|
|
||||||
|
|
||||||
assertEqual(5, collection.count());
|
|
||||||
assertEqual([6, 7, 8, 9, 10], collection.toArray().map(fun).sort(nsort));
|
|
||||||
|
|
||||||
collection.save({ n: 0 });
|
|
||||||
assertEqual([0, 7, 8, 9, 10], collection.toArray().map(fun).sort(nsort));
|
|
||||||
},
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// @brief test: cap with byteSize
|
/// @brief test: cap with byteSize
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
|
@ -1577,8 +1577,15 @@ function resultOk (req, res, httpReturnCode, result, headers) {
|
||||||
result = {};
|
result = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// check the type of the result.
|
||||||
|
if (typeof result !== "string" &&
|
||||||
|
typeof result !== "number" &&
|
||||||
|
typeof result !== "boolean") {
|
||||||
|
// only modify result properties if none of the above types
|
||||||
|
// otherwise the strict mode will throw
|
||||||
result.error = false;
|
result.error = false;
|
||||||
result.code = httpReturnCode;
|
result.code = httpReturnCode;
|
||||||
|
}
|
||||||
|
|
||||||
res.body = JSON.stringify(result);
|
res.body = JSON.stringify(result);
|
||||||
|
|
||||||
|
|
|
@ -493,6 +493,9 @@ shutdownActions.startServers = function (dispatchers, cmd, run) {
|
||||||
var i;
|
var i;
|
||||||
var url;
|
var url;
|
||||||
var r;
|
var r;
|
||||||
|
var serverStates = {};
|
||||||
|
var error = false;
|
||||||
|
|
||||||
for (i = 0;i < run.endpoints.length;i++) {
|
for (i = 0;i < run.endpoints.length;i++) {
|
||||||
console.info("Using API to shutdown %s", JSON.stringify(run.pids[i]));
|
console.info("Using API to shutdown %s", JSON.stringify(run.pids[i]));
|
||||||
url = endpointToURL(run.endpoints[i])+"/_admin/shutdown";
|
url = endpointToURL(run.endpoints[i])+"/_admin/shutdown";
|
||||||
|
@ -514,13 +517,20 @@ shutdownActions.startServers = function (dispatchers, cmd, run) {
|
||||||
for (i = 0;i < run.pids.length;i++) {
|
for (i = 0;i < run.pids.length;i++) {
|
||||||
var s = statusExternal(run.pids[i]);
|
var s = statusExternal(run.pids[i]);
|
||||||
if (s.status !== "TERMINATED") {
|
if (s.status !== "TERMINATED") {
|
||||||
|
if (s.hasOwnProperty('signal')) {
|
||||||
|
error = true;
|
||||||
|
console.info("done - with problems: " + s);
|
||||||
|
}
|
||||||
|
else {
|
||||||
console.info("Shutting down %s the hard way...",
|
console.info("Shutting down %s the hard way...",
|
||||||
JSON.stringify(run.pids[i]));
|
JSON.stringify(run.pids[i]));
|
||||||
killExternal(run.pids[i]);
|
s.killedState = killExternal(run.pids[i]);
|
||||||
console.info("done.");
|
console.info("done.");
|
||||||
}
|
}
|
||||||
|
serverStates[run.pids[i]] = s;
|
||||||
}
|
}
|
||||||
return {"error": false, "isStartServers": true};
|
}
|
||||||
|
return {"error": error, "isStartServers": true, "serverStates" : serverStates};
|
||||||
};
|
};
|
||||||
|
|
||||||
cleanupActions.startAgent = function (dispatchers, cmd) {
|
cleanupActions.startAgent = function (dispatchers, cmd) {
|
||||||
|
|
|
@ -152,7 +152,7 @@ BaseMiddleware = function () {
|
||||||
///
|
///
|
||||||
/// `request.requestParts()`
|
/// `request.requestParts()`
|
||||||
///
|
///
|
||||||
/// Returns a list containing the individual parts of a multi-part request.
|
/// Returns an array containing the individual parts of a multi-part request.
|
||||||
/// Each part contains a `headers` attribute with all headers of the part,
|
/// Each part contains a `headers` attribute with all headers of the part,
|
||||||
/// and a `data` attribute with the content of the part in a Buffer object.
|
/// and a `data` attribute with the content of the part in a Buffer object.
|
||||||
/// If the request is not a multi-part request, this function will throw an
|
/// If the request is not a multi-part request, this function will throw an
|
||||||
|
|
|
@ -24,10 +24,11 @@
|
||||||
///
|
///
|
||||||
/// Copyright holder is triAGENS GmbH, Cologne, Germany
|
/// Copyright holder is triAGENS GmbH, Cologne, Germany
|
||||||
///
|
///
|
||||||
/// @author Dr. Frank Celler
|
/// @author Dr. Frank Celler, Michael Hackstein
|
||||||
/// @author Copyright 2013, triAGENS GmbH, Cologne, Germany
|
/// @author Copyright 2013, triAGENS GmbH, Cologne, Germany
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
/*
|
||||||
var arangodb = require("org/arangodb");
|
var arangodb = require("org/arangodb");
|
||||||
var ArangoError = arangodb.ArangoError;
|
var ArangoError = arangodb.ArangoError;
|
||||||
var errors = arangodb.errors;
|
var errors = arangodb.errors;
|
||||||
|
@ -50,6 +51,7 @@ var download = require("internal").download;
|
||||||
var throwDownloadError = arangodb.throwDownloadError;
|
var throwDownloadError = arangodb.throwDownloadError;
|
||||||
var throwFileNotFound = arangodb.throwFileNotFound;
|
var throwFileNotFound = arangodb.throwFileNotFound;
|
||||||
|
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
// --SECTION-- private functions
|
// --SECTION-- private functions
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
@ -177,52 +179,6 @@ function checkManifest (filename, mf) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
/// @brief extend a context with some helper functions
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
function extendContext (context, app, root) {
|
|
||||||
"use strict";
|
|
||||||
|
|
||||||
var cp = context.collectionPrefix;
|
|
||||||
var cname = "";
|
|
||||||
|
|
||||||
if (cp === "_") {
|
|
||||||
cname = "_";
|
|
||||||
}
|
|
||||||
else if (cp !== "") {
|
|
||||||
cname = cp + "_";
|
|
||||||
}
|
|
||||||
|
|
||||||
context.collectionName = function (name) {
|
|
||||||
var replaced = cname + name.replace(/[^a-zA-Z0-9]/g, '_').replace(/(^_+|_+$)/g, '').substr(0, 64);
|
|
||||||
|
|
||||||
if (replaced.length === 0) {
|
|
||||||
throw new Error("Cannot derive collection name from '" + name + "'");
|
|
||||||
}
|
|
||||||
|
|
||||||
return replaced;
|
|
||||||
};
|
|
||||||
|
|
||||||
context.collection = function (name) {
|
|
||||||
return arangodb.db._collection(this.collectionName(name));
|
|
||||||
};
|
|
||||||
|
|
||||||
context.path = function (name) {
|
|
||||||
return fs.join(root, app._path, name);
|
|
||||||
};
|
|
||||||
|
|
||||||
context.comments = [];
|
|
||||||
|
|
||||||
context.comment = function (str) {
|
|
||||||
this.comments.push(str);
|
|
||||||
};
|
|
||||||
|
|
||||||
context.clearComments = function () {
|
|
||||||
this.comments = [];
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// @brief finds mount document from mount path or identifier
|
/// @brief finds mount document from mount path or identifier
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -865,40 +821,6 @@ exports.mount = function (appId, mount, options) {
|
||||||
return { appId: app._id, mountId: doc._key, mount: mount };
|
return { appId: app._id, mountId: doc._key, mount: mount };
|
||||||
};
|
};
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
/// @brief tears down a Foxx application
|
|
||||||
///
|
|
||||||
/// Input:
|
|
||||||
/// * mount: the mount path starting with a "/"
|
|
||||||
///
|
|
||||||
/// Output:
|
|
||||||
/// -
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
exports.teardown = function (mount) {
|
|
||||||
"use strict";
|
|
||||||
|
|
||||||
checkParameter(
|
|
||||||
"teardown(<mount>)",
|
|
||||||
[ [ "Mount identifier", "string" ] ],
|
|
||||||
[ mount ] );
|
|
||||||
|
|
||||||
var appId;
|
|
||||||
|
|
||||||
try {
|
|
||||||
var doc = mountFromId(mount);
|
|
||||||
|
|
||||||
appId = doc.app;
|
|
||||||
var app = createApp(appId);
|
|
||||||
|
|
||||||
teardownApp(app, mount, doc.options.collectionPrefix);
|
|
||||||
} catch (err) {
|
|
||||||
console.errorLines(
|
|
||||||
"Teardown not possible for mount '%s': %s", mount, String(err.stack || err));
|
|
||||||
throw err;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// @brief unmounts a Foxx application
|
/// @brief unmounts a Foxx application
|
||||||
///
|
///
|
||||||
|
@ -1209,16 +1131,6 @@ exports.fetchFromGithub = function (url, name, version) {
|
||||||
return "app:" + source.name + ":" + source.version;
|
return "app:" + source.name + ":" + source.version;
|
||||||
};
|
};
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
///// @brief returns all installed FOXX applications
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
exports.listJson = function () {
|
|
||||||
"use strict";
|
|
||||||
|
|
||||||
return utils.listJson();
|
|
||||||
};
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// @brief initializes the Foxx apps
|
/// @brief initializes the Foxx apps
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -1287,6 +1199,7 @@ exports.initializeFoxx = function () {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
*/
|
||||||
|
|
||||||
(function() {
|
(function() {
|
||||||
"use strict";
|
"use strict";
|
||||||
|
@ -1294,6 +1207,22 @@ exports.initializeFoxx = function () {
|
||||||
// --CHAPTER-- used code
|
// --CHAPTER-- used code
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
// --SECTION-- imports
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
var fs = require("fs");
|
||||||
|
var utils = require("org/arangodb/foxx/manager-utils");
|
||||||
|
var store = require("org/arangodb/foxx/store");
|
||||||
|
var arangodb = require("org/arangodb");
|
||||||
|
var ArangoError = arangodb.ArangoError;
|
||||||
|
var checkParameter = arangodb.checkParameter;
|
||||||
|
var errors = arangodb.errors;
|
||||||
|
var download = require("internal").download;
|
||||||
|
|
||||||
|
var throwDownloadError = arangodb.throwDownloadError;
|
||||||
|
var throwFileNotFound = arangodb.throwFileNotFound;
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
// --SECTION-- private variables
|
// --SECTION-- private variables
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
@ -1321,6 +1250,52 @@ var prefixFromMount = function(mount) {
|
||||||
return mount.substr(1).replace(/-/g, "_").replace(/\//g, "_");
|
return mount.substr(1).replace(/-/g, "_").replace(/\//g, "_");
|
||||||
};
|
};
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @brief extend a context with some helper functions
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
var extendContext = function(context, app, root) {
|
||||||
|
var cp = context.collectionPrefix;
|
||||||
|
var cname = "";
|
||||||
|
|
||||||
|
if (cp === "_") {
|
||||||
|
cname = "_";
|
||||||
|
}
|
||||||
|
else if (cp !== "") {
|
||||||
|
cname = cp + "_";
|
||||||
|
}
|
||||||
|
|
||||||
|
context.collectionName = function (name) {
|
||||||
|
var replaced = cname + name.replace(/[^a-zA-Z0-9]/g, '_').replace(/(^_+|_+$)/g, '').substr(0, 64);
|
||||||
|
|
||||||
|
if (replaced.length === 0) {
|
||||||
|
throw new Error("Cannot derive collection name from '" + name + "'");
|
||||||
|
}
|
||||||
|
|
||||||
|
return replaced;
|
||||||
|
};
|
||||||
|
|
||||||
|
context.collection = function (name) {
|
||||||
|
return arangodb.db._collection(this.collectionName(name));
|
||||||
|
};
|
||||||
|
|
||||||
|
context.path = function (name) {
|
||||||
|
return fs.join(root, app._path, name);
|
||||||
|
};
|
||||||
|
|
||||||
|
context.comments = [];
|
||||||
|
|
||||||
|
context.comment = function (str) {
|
||||||
|
this.comments.push(str);
|
||||||
|
};
|
||||||
|
|
||||||
|
context.clearComments = function () {
|
||||||
|
this.comments = [];
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// @brief validates a manifest file and returns it.
|
/// @brief validates a manifest file and returns it.
|
||||||
/// All errors are handled including file not found. Returns undefined if manifest is invalid
|
/// All errors are handled including file not found. Returns undefined if manifest is invalid
|
||||||
|
@ -1348,16 +1323,22 @@ var validateManifestFile = function(file) {
|
||||||
return mf;
|
return mf;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @brief Checks if the mountpoint is reserved for system apps
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
var isSystemMount = function(mount) {
|
||||||
|
return (/^\/_/).test(mount);
|
||||||
|
};
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// @brief returns the root path for application. Knows about system apps
|
/// @brief returns the root path for application. Knows about system apps
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
var computeRootAppPath = function(mount) {
|
var computeRootAppPath = function(mount) {
|
||||||
if (/^\/_/.test(mount)) {
|
if (isSystemMount(mount)) {
|
||||||
// Must be a system app
|
|
||||||
return module.systemAppPath();
|
return module.systemAppPath();
|
||||||
}
|
}
|
||||||
// A standard app
|
|
||||||
return module.appPath();
|
return module.appPath();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1366,7 +1347,9 @@ var computeRootAppPath = function(mount) {
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
var transformMountToPath = function(mount) {
|
var transformMountToPath = function(mount) {
|
||||||
return fs.join.apply(this, mount.split("/").push("APP"));
|
var list = mount.split("/");
|
||||||
|
list.push("APP");
|
||||||
|
return fs.join.apply(this, list);
|
||||||
};
|
};
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -1415,36 +1398,29 @@ var executeAppScript = function(app, name, mount, prefix) {
|
||||||
|
|
||||||
app.loadAppScript(appContext, desc[name]);
|
app.loadAppScript(appContext, desc[name]);
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// @brief sets up an app
|
/// @brief sets up an app
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
function setupApp (app, mount, prefix) {
|
var setupApp = function (app, mount, prefix) {
|
||||||
"use strict";
|
|
||||||
|
|
||||||
return executeAppScript(app, "setup", mount, prefix);
|
return executeAppScript(app, "setup", mount, prefix);
|
||||||
}
|
};
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// @brief tears down an app
|
/// @brief tears down an app
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
function teardownApp (app, mount, prefix) {
|
var teardownApp = function (app, mount, prefix) {
|
||||||
"use strict";
|
|
||||||
|
|
||||||
return executeAppScript(app, "teardown", mount, prefix);
|
return executeAppScript(app, "teardown", mount, prefix);
|
||||||
}
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// @brief returns the app path and manifest
|
/// @brief returns the app path and manifest
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
var appDescription = function (mount, options) {
|
var appConfig = function (mount, options) {
|
||||||
|
|
||||||
var root = computeRootAppPath(mount);
|
var root = computeRootAppPath(mount);
|
||||||
var path = transformMountToPath(mount);
|
var path = transformMountToPath(mount);
|
||||||
|
@ -1462,7 +1438,10 @@ function teardownApp (app, mount, prefix) {
|
||||||
root: root,
|
root: root,
|
||||||
path: path,
|
path: path,
|
||||||
manifest: manifest,
|
manifest: manifest,
|
||||||
options: options
|
options: options,
|
||||||
|
mount: mount,
|
||||||
|
isSystem: isSystemMount(mount),
|
||||||
|
isDevelopment: false
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1473,8 +1452,9 @@ function teardownApp (app, mount, prefix) {
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
var createApp = function(mount, options) {
|
var createApp = function(mount, options) {
|
||||||
var description = appDescription(mount);
|
var config = appConfig(mount);
|
||||||
var app = module.createApp(description, options || {});
|
config.options = options || {};
|
||||||
|
var app = module.createApp(config);
|
||||||
if (app === null) {
|
if (app === null) {
|
||||||
console.errorLines(
|
console.errorLines(
|
||||||
"Cannot find application '%s'", mount);
|
"Cannot find application '%s'", mount);
|
||||||
|
@ -1632,7 +1612,7 @@ var installAppFromLocal = function(path, targetPath) {
|
||||||
/// @brief sets up a Foxx application
|
/// @brief sets up a Foxx application
|
||||||
///
|
///
|
||||||
/// Input:
|
/// Input:
|
||||||
/// * mount: the mount identifier or path
|
/// * mount: the mount path starting with a "/"
|
||||||
///
|
///
|
||||||
/// Output:
|
/// Output:
|
||||||
/// -
|
/// -
|
||||||
|
@ -1655,6 +1635,32 @@ var setup = function (mount) {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @brief tears down a Foxx application
|
||||||
|
///
|
||||||
|
/// Input:
|
||||||
|
/// * mount: the mount path starting with a "/"
|
||||||
|
///
|
||||||
|
/// Output:
|
||||||
|
/// -
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
var teardown = function (mount) {
|
||||||
|
checkParameter(
|
||||||
|
"teardown(<mount>)",
|
||||||
|
[ [ "Mount path", "string" ] ],
|
||||||
|
[ mount ] );
|
||||||
|
|
||||||
|
var app = lookupApp(mount);
|
||||||
|
try {
|
||||||
|
teardownApp(app, mount, prefixFromMount(mount));
|
||||||
|
} catch (err) {
|
||||||
|
console.errorLines(
|
||||||
|
"Teardown not possible for mount '%s': %s", mount, String(err.stack || err));
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// @brief Scans the sources of the given mountpoint and publishes the routes
|
/// @brief Scans the sources of the given mountpoint and publishes the routes
|
||||||
///
|
///
|
||||||
|
@ -1662,22 +1668,16 @@ var setup = function (mount) {
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
var scanFoxx = function(mount, options) {
|
var scanFoxx = function(mount, options) {
|
||||||
delete appCache[mount];
|
delete appCache[mount];
|
||||||
createApp(mount, options);
|
var app = createApp(mount, options);
|
||||||
|
utils.tmp_getStorage().save(app.toJSON());
|
||||||
|
// TODO Routing?
|
||||||
};
|
};
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// @brief Installs a new foxx application on the given mount point.
|
/// @brief Internal install function. Check install.
|
||||||
///
|
/// Does not check parameters and throws errors.
|
||||||
/// TODO: Long Documentation!
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
var install = function(appInfo, mount, options) {
|
var _install = function(appInfo, mount, options, runSetup) {
|
||||||
|
|
||||||
checkParameter(
|
|
||||||
"mount(<appInfo>, <mount>, [<options>])",
|
|
||||||
[ [ "Install information", "string" ],
|
|
||||||
[ "Mount path", "string" ] ],
|
|
||||||
[ appInfo, mount ] );
|
|
||||||
|
|
||||||
var targetPath = computeAppPath(mount, true);
|
var targetPath = computeAppPath(mount, true);
|
||||||
if (fs.exists(targetPath)) {
|
if (fs.exists(targetPath)) {
|
||||||
throw "An app is already installed at this location.";
|
throw "An app is already installed at this location.";
|
||||||
|
@ -1685,7 +1685,7 @@ var install = function(appInfo, mount, options) {
|
||||||
fs.makeDirectoryRecursive(targetPath);
|
fs.makeDirectoryRecursive(targetPath);
|
||||||
// Remove the empty APP folder.
|
// Remove the empty APP folder.
|
||||||
// Ohterwise move will fail.
|
// Ohterwise move will fail.
|
||||||
fs.removeDirectoryRecursive(targetPath);
|
fs.removeDirectory(targetPath);
|
||||||
|
|
||||||
if (appInfo === "EMPTY") {
|
if (appInfo === "EMPTY") {
|
||||||
// Make Empty app
|
// Make Empty app
|
||||||
|
@ -1701,27 +1701,110 @@ var install = function(appInfo, mount, options) {
|
||||||
throw "Not implemented yet";
|
throw "Not implemented yet";
|
||||||
}
|
}
|
||||||
scanFoxx(mount, options);
|
scanFoxx(mount, options);
|
||||||
|
if (runSetup) {
|
||||||
setup(mount);
|
setup(mount);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @brief Installs a new foxx application on the given mount point.
|
||||||
|
///
|
||||||
|
/// TODO: Long Documentation!
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
var install = function(appInfo, mount, options) {
|
||||||
|
checkParameter(
|
||||||
|
"mount(<appInfo>, <mount>, [<options>])",
|
||||||
|
[ [ "Install information", "string" ],
|
||||||
|
[ "Mount path", "string" ] ],
|
||||||
|
[ appInfo, mount ] );
|
||||||
|
_install(appInfo, mount, options, true);
|
||||||
|
};
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @brief Internal install function. Check install.
|
||||||
|
/// Does not check parameters and throws errors.
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
var _uninstall = function(mount) {
|
||||||
|
var targetPath = computeAppPath(mount, true);
|
||||||
|
if (!fs.exists(targetPath)) {
|
||||||
|
throw "No foxx app found at this location.";
|
||||||
|
}
|
||||||
|
teardown(mount);
|
||||||
|
// TODO Delete routing?
|
||||||
|
utils.tmp_getStorage().removeByExample({mount: mount});
|
||||||
|
delete appCache[mount];
|
||||||
|
// Remove the APP folder.
|
||||||
|
fs.removeDirectoryRecursive(targetPath, true);
|
||||||
|
};
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @brief Uninstalls the foxx application on the given mount point.
|
||||||
|
///
|
||||||
|
/// TODO: Long Documentation!
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
var uninstall = function(mount) {
|
||||||
|
checkParameter(
|
||||||
|
"mount(<mount>)",
|
||||||
|
[ [ "Mount path", "string" ] ],
|
||||||
|
[ mount ] );
|
||||||
|
_uninstall(mount);
|
||||||
|
};
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @brief Replaces a foxx application on the given mount point by an other one.
|
||||||
|
///
|
||||||
|
/// TODO: Long Documentation!
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
var replace = function(appInfo, mount, options) {
|
||||||
|
checkParameter(
|
||||||
|
"mount(<appInfo>, <mount>, [<options>])",
|
||||||
|
[ [ "Install information", "string" ],
|
||||||
|
[ "Mount path", "string" ] ],
|
||||||
|
[ appInfo, mount ] );
|
||||||
|
_uninstall(mount, true);
|
||||||
|
_install(appInfo, mount, options, true);
|
||||||
|
};
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @brief Upgrade a foxx application on the given mount point by a new one.
|
||||||
|
///
|
||||||
|
/// TODO: Long Documentation!
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
var upgrade = function(appInfo, mount, options) {
|
||||||
|
checkParameter(
|
||||||
|
"mount(<appInfo>, <mount>, [<options>])",
|
||||||
|
[ [ "Install information", "string" ],
|
||||||
|
[ "Mount path", "string" ] ],
|
||||||
|
[ appInfo, mount ] );
|
||||||
|
_uninstall(mount, false);
|
||||||
|
_install(appInfo, mount, options, false);
|
||||||
|
};
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
// --SECTION-- exports
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// @brief Exports
|
/// @brief Exports
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
exports.scanFoxx = scanFoxx;
|
||||||
exports.install = install;
|
exports.install = install;
|
||||||
/*
|
|
||||||
exports.uninstall = uninstall;
|
|
||||||
exports.setup = setup;
|
exports.setup = setup;
|
||||||
exports.teardown = teardown;
|
exports.teardown = teardown;
|
||||||
exports.list = list;
|
exports.uninstall = uninstall;
|
||||||
exports.listJson = listJson;
|
|
||||||
exports.replace = replace;
|
exports.replace = replace;
|
||||||
exports.mountedApp = mountedApp;
|
|
||||||
exports.upgrade = upgrade;
|
exports.upgrade = upgrade;
|
||||||
exports.scanFoxx = scanFoxx;
|
|
||||||
exports.developmentMounts = developmentMounts;
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
exports.developmentMountsJson = developmentMountsJson;
|
/// @brief Exports from foxx utils module.
|
||||||
*/
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
exports.mountedApp = utils.mountedApp;
|
||||||
|
exports.list = utils.list;
|
||||||
|
exports.listJson = utils.listJson;
|
||||||
|
exports.listDevelopment = utils.listDevelopment;
|
||||||
|
exports.listDevelopmentJson = utils.listDevelopmentJson;
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// @brief Exports from foxx store module.
|
/// @brief Exports from foxx store module.
|
||||||
|
|
|
@ -98,6 +98,7 @@ var Planner = require("org/arangodb/cluster").Planner;
|
||||||
var Kickstarter = require("org/arangodb/cluster").Kickstarter;
|
var Kickstarter = require("org/arangodb/cluster").Kickstarter;
|
||||||
|
|
||||||
var endpointToURL = require("org/arangodb/cluster/planner").endpointToURL;
|
var endpointToURL = require("org/arangodb/cluster/planner").endpointToURL;
|
||||||
|
var serverCrashed = false;
|
||||||
|
|
||||||
var optionsDefaults = { "cluster": false,
|
var optionsDefaults = { "cluster": false,
|
||||||
"valgrind": false,
|
"valgrind": false,
|
||||||
|
@ -394,6 +395,9 @@ function checkInstanceAlive(instanceInfo, options) {
|
||||||
copy("bin/arangod", storeArangodPath);
|
copy("bin/arangod", storeArangodPath);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (!ret) {
|
||||||
|
serverCrashed = true;
|
||||||
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
var ClusterFit = true;
|
var ClusterFit = true;
|
||||||
|
@ -419,30 +423,69 @@ function checkInstanceAlive(instanceInfo, options) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ClusterFit && instanceInfo.kickstarter.isHealthy();
|
if (ClusterFit && instanceInfo.kickstarter.isHealthy()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
serverCrashed = true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function shutdownInstance (instanceInfo, options) {
|
function shutdownInstance (instanceInfo, options) {
|
||||||
|
if (!checkInstanceAlive(instanceInfo, options)) {
|
||||||
|
print("Server already dead, doing nothing. This shouldn't happen?");
|
||||||
|
}
|
||||||
if (options.cluster) {
|
if (options.cluster) {
|
||||||
instanceInfo.kickstarter.shutdown();
|
var rc = instanceInfo.kickstarter.shutdown();
|
||||||
if (options.cleanup) {
|
if (options.cleanup) {
|
||||||
instanceInfo.kickstarter.cleanup();
|
instanceInfo.kickstarter.cleanup();
|
||||||
}
|
}
|
||||||
|
if (rc.error) {
|
||||||
|
for (var i in rc.serverStates) {
|
||||||
|
if (rc.serverStates.hasOwnProperty(i)){
|
||||||
|
if (rc.serverStates[i].hasOwnProperty('signal')) {
|
||||||
|
print("Server shut down with : " + rc.serverStates[i] + " marking run as crashy.");
|
||||||
|
serverCrashed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (typeof(instanceInfo.exitStatus) === 'undefined') {
|
if (typeof(instanceInfo.exitStatus) === 'undefined') {
|
||||||
download(instanceInfo.url+"/_admin/shutdown","",
|
download(instanceInfo.url+"/_admin/shutdown","",
|
||||||
makeAuthorisationHeaders(options));
|
makeAuthorisationHeaders(options));
|
||||||
|
|
||||||
if (typeof(options.valgrind) === 'string') {
|
|
||||||
print("Waiting for server shut down");
|
print("Waiting for server shut down");
|
||||||
var res = statusExternal(instanceInfo.pid, true);
|
var count = 0;
|
||||||
print("Server gone: ");
|
while (1) {
|
||||||
print(res);
|
instanceInfo.exitStatus = statusExternal(instanceInfo.pid, false);
|
||||||
|
if (instanceInfo.exitStatus.status === "RUNNING") {
|
||||||
|
count ++;
|
||||||
|
if (typeof(options.valgrind) === 'string') {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (count > 10) {
|
||||||
|
print("forcefully terminating " + instanceInfo.pid + " after 10 s grace period.");
|
||||||
|
serverCrashed = true;
|
||||||
|
killExternal(instanceInfo.pid);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
wait(10);
|
wait(1);
|
||||||
killExternal(instanceInfo.pid);
|
}
|
||||||
|
}
|
||||||
|
else if (instanceInfo.exitStatus.status !== "TERMINATED") {
|
||||||
|
if (instanceInfo.exitStatus.hasOwnProperty('signal')) {
|
||||||
|
print("Server shut down with : " + instanceInfo.exitStatus + " marking build as crashy.");
|
||||||
|
serverCrashed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
print("Server shutdown: Success.");
|
||||||
|
break; // Success.
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -1485,7 +1528,7 @@ testFuncs.authentication_parameters = function (options) {
|
||||||
return results;
|
return results;
|
||||||
};
|
};
|
||||||
|
|
||||||
var internalMembers = ["code", "error", "status", "duration", "failed", "total"];
|
var internalMembers = ["code", "error", "status", "duration", "failed", "total", "crashed", "all_ok", "ok", "message"];
|
||||||
|
|
||||||
function unitTestPrettyPrintResults(r) {
|
function unitTestPrettyPrintResults(r) {
|
||||||
var testrun;
|
var testrun;
|
||||||
|
@ -1498,13 +1541,13 @@ function unitTestPrettyPrintResults(r) {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
for (testrun in r) {
|
for (testrun in r) {
|
||||||
if (r.hasOwnProperty(testrun) && (testrun !== 'all_ok')) {
|
if (r.hasOwnProperty(testrun) && (internalMembers.indexOf(testrun) === -1)) {
|
||||||
var isSuccess = true;
|
var isSuccess = true;
|
||||||
var oneOutput = "";
|
var oneOutput = "";
|
||||||
|
|
||||||
oneOutput = "Testrun: " + testrun + "\n";
|
oneOutput = "Testrun: " + testrun + "\n";
|
||||||
for (test in r[testrun]) {
|
for (test in r[testrun]) {
|
||||||
if (r[testrun].hasOwnProperty(test) && (test !== 'ok')) {
|
if (r[testrun].hasOwnProperty(test) && (internalMembers.indexOf(test) === -1)) {
|
||||||
if (r[testrun][test].status) {
|
if (r[testrun][test].status) {
|
||||||
oneOutput += " [Success] " + test + "\n";
|
oneOutput += " [Success] " + test + "\n";
|
||||||
}
|
}
|
||||||
|
@ -1599,6 +1642,7 @@ function UnitTest (which, options) {
|
||||||
results.all_ok = allok;
|
results.all_ok = allok;
|
||||||
}
|
}
|
||||||
results.all_ok = allok;
|
results.all_ok = allok;
|
||||||
|
results.crashed = serverCrashed;
|
||||||
if (allok) {
|
if (allok) {
|
||||||
cleanupDBDirectories(options);
|
cleanupDBDirectories(options);
|
||||||
}
|
}
|
||||||
|
@ -1634,6 +1678,7 @@ function UnitTest (which, options) {
|
||||||
}
|
}
|
||||||
r.ok = ok;
|
r.ok = ok;
|
||||||
results.all_ok = ok;
|
results.all_ok = ok;
|
||||||
|
results.crashed = serverCrashed;
|
||||||
|
|
||||||
if (allok) {
|
if (allok) {
|
||||||
cleanupDBDirectories(options);
|
cleanupDBDirectories(options);
|
||||||
|
@ -1652,6 +1697,7 @@ function UnitTest (which, options) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
exports.internalMembers = internalMembers;
|
||||||
exports.testFuncs = testFuncs;
|
exports.testFuncs = testFuncs;
|
||||||
exports.UnitTest = UnitTest;
|
exports.UnitTest = UnitTest;
|
||||||
exports.unitTestPrettyPrintResults = unitTestPrettyPrintResults;
|
exports.unitTestPrettyPrintResults = unitTestPrettyPrintResults;
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
/*jshint unused: false */
|
/*jshint unused: false */
|
||||||
/*global require, start_pretty_print */
|
/*global require, start_pretty_print */
|
||||||
|
|
||||||
var internalMembers = ["code", "error", "status", "duration", "failed", "total", "message"];
|
var UnitTest = require("org/arangodb/testing");
|
||||||
|
|
||||||
|
var internalMembers = UnitTest.internalMembers;
|
||||||
var fs = require("fs");
|
var fs = require("fs");
|
||||||
var print = require("internal").print;
|
var print = require("internal").print;
|
||||||
|
|
||||||
|
@ -46,10 +48,10 @@ function resultsToXml(results, baseName) {
|
||||||
}
|
}
|
||||||
|
|
||||||
for (var testrun in results) {
|
for (var testrun in results) {
|
||||||
if ((testrun !== "all_ok") && (results.hasOwnProperty(testrun))) {
|
if ((internalMembers.indexOf(testrun) === -1) && (results.hasOwnProperty(testrun))) {
|
||||||
for (var test in results[testrun]) {
|
for (var test in results[testrun]) {
|
||||||
|
|
||||||
if ((test !== "ok") &&
|
if ((internalMembers.indexOf(test) === -1) &&
|
||||||
results[testrun].hasOwnProperty(test) &&
|
results[testrun].hasOwnProperty(test) &&
|
||||||
!results[testrun][test].hasOwnProperty('skipped')) {
|
!results[testrun][test].hasOwnProperty('skipped')) {
|
||||||
|
|
||||||
|
@ -127,7 +129,6 @@ function main (argv) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
options.jsonReply = true;
|
options.jsonReply = true;
|
||||||
var UnitTest = require("org/arangodb/testing");
|
|
||||||
start_pretty_print();
|
start_pretty_print();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
@ -139,7 +140,7 @@ function main (argv) {
|
||||||
print(JSON.stringify(r));
|
print(JSON.stringify(r));
|
||||||
}
|
}
|
||||||
fs.write("UNITTEST_RESULT.json",JSON.stringify(r));
|
fs.write("UNITTEST_RESULT.json",JSON.stringify(r));
|
||||||
fs.write("UNITTEST_RESULT_SUMMARY.txt",JSON.stringify(r.all_ok));
|
fs.write("UNITTEST_RESULT_SUMMARY.txt",JSON.stringify(!r.crashed));
|
||||||
try {
|
try {
|
||||||
resultsToXml(r, "UNITTEST_RESULT_");
|
resultsToXml(r, "UNITTEST_RESULT_");
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue