blockstack-storage
Version:
The Blockstack Javascript library for storage.
653 lines (530 loc) • 22.2 kB
JavaScript
import {
createDatastore,
deleteDatastore,
getDatastore,
datastoreMkdir,
datastoreRmdir,
datastoreListdir,
datastoreGetFile,
datastorePutFile,
datastoreDeleteFile,
datastoreStat,
getOrCreateDatastore
} from './testlib';
import {
datastoreGetId,
decodePrivateKey,
} from '../../../lib/';
import {
makeInodeHeaderBlob
} from '../../../lib/';
import {
getCoreSession,
makeAuthRequest
} from "blockstack";
const assert = require('assert');
const bitcoinjs = require('bitcoinjs-lib');
const http = require('http');
const jsontokens = require('jsontokens');
const BigInteger = require('bigi');
const Promise = require('promise');
var args = process.argv.slice(2);
var command = null;
if( args.length == 0 ) {
command = "unittest";
}
else {
command = args[0];
}
var res = null;
function dir_expect(dir, names) {
for (var name of names) {
if( !Object.keys(dir['children']).includes(name) ) {
return false;
}
}
return true;
}
function dir_absent(ds_str, dir_path) {
return datastoreListdir(ds_str, dir_path).then(
(idata) => {
console.log(`listdir ${dir_path} got result: ${JSON.stringify(idata)}`);
return false;
},
(error) => {
console.log(`listdir ${dir_path} failed`);
console.log(error);
console.log(JSON.stringify(error));
return true;
});
}
function stat_dir(ds_str, dir_path, expect_error) {
return datastoreStat(ds_str, dir_path).then(
(inode) => {
console.log(`stat dir ${dir_path} got result: ${JSON.stringify(inode)}`);
assert(inode);
assert(!inode.error);
assert(!inode.errno);
if( inode.type != 2 ) {
console.log(inode);
return false;
}
return true;
},
(error) => {
console.log(`stat ${dir_path} failed`);
console.log(error);
console.log(JSON.stringify(error));
if (expect_error) {
return true;
}
else {
return false;
}
});
}
function stat_file(ds_str, file_path, expect_error) {
return datastoreStat(ds_str, file_path).then(
(inode) => {
console.log(`stat file ${file_path} got result: ${JSON.stringify(inode)}`);
assert(inode);
assert(!inode.error);
assert(!inode.errno);
if( inode.type != 1 ) {
console.log(inode);
return false;
}
return true;
},
(error) => {
console.log(`stat ${file_path} failed`);
console.log(error);
console.log(JSON.stringify(error));
if (expect_error) {
return true;
}
else {
return false;
}
});
}
function file_expect(ds_str, file_path, content) {
return datastoreGetFile(ds_str, file_path).then(
(idata) => {
console.log(`getfile ${file_path} got result: ${JSON.stringify(idata)}`);
if( idata.error || !idata ) {
if( expect_error ) {
return true;
}
else {
console.log(idata.error);
return false;
}
}
if( idata != content ) {
console.log(`expected ${content}; got ${idata}`);
}
return true;
},
(error) => {
console.log(`getfile ${file_path} failed`);
console.log(error);
console.log(JSON.stringify(error));
return false;
});
}
function file_absent(ds_str, file_path) {
return datastoreGetFile(ds_str, file_path).then(
(idata) => {
console.log(`getfile ${file_path} got result: ${JSON.stringify(idata)}`);
if (idata) {
return false;
}
else {
return true;
}
},
(error) => {
console.log(`getfile ${file_path} failed`);
console.log(error);
console.log(JSON.stringify(error));
return false;
});
}
function http_request(options) {
var p = new Promise(function(resolve, reject) {
http.request(options, function(response) {
var strbuf = [];
response.on('data', function(chunk) {
strbuf.push(chunk);
});
response.on('end', function() {
if( response.statusCode != 200 ) {
return reject("HTTP Status " + response.statusCode);
}
var str = Buffer.concat(strbuf).toString();
var resp = JSON.parse(str);
str = null;
strbuf = null;
resolve(resp);
});
response.on('error', function() {
reject(resp);
});
}).end();
});
return p;
}
function node_ping(host, port) {
var options = {
'method': 'GET',
'host': host,
'port': port,
'path': '/v1/node/ping',
};
return http_request(options);
}
if( command == 'createDatastore' ) {
assert(args.length >= 5);
res = createDatastore(args[1], args[2], args[3], args[4], args[5])
}
else if( command == 'deleteDatastore') {
assert(args.length >= 2);
res = deleteDatastore(args[1]);
}
else if( command == 'getDatastore') {
assert(args.length >= 5);
res = getDatastore(args[1], args[2], args[3], args[4]);
}
else if( command == 'mkdir' ) {
assert(args.length >= 3);
res = datastoreMkdir(args[1], args[2], args[3], args[4]);
}
else if( command == 'rmdir' ) {
assert(args.length >= 3);
res = datastoreRmdir(args[1], args[2], args[3], args[4]);
}
else if( command == 'listdir' ) {
assert(args.length >= 3 );
res = datastoreListdir(args[1], args[2], args[3], args[4]);
}
else if( command == 'getfile' ) {
assert(args.length >= 3);
res = datastoreGetFile(args[1], args[2], args[3], args[4]);
}
else if( command == 'putfile' ) {
assert(args.length >= 4);
res = datastorePutFile(args[1], args[2], args[3], args[4], args[5]);
}
else if( command == 'deletefile' ) {
assert(args.length >= 3);
res = datastoreDeleteFile(args[1], args[2]);
}
else if( command == 'stat' ) {
assert(args.length >= 3 );
res = datastoreStat(args[1], args[2]);
}
else if( command == 'unittest' ) {
var hdr = makeInodeHeaderBlob("1BjnYXfXbh84Xrc24zM1GFvCrXenp8AqUZ", 2, "1BjnYXfXbh84Xrc24zM1GFvCrXenp8AqUZ", "86ce29a7-0714-4136-bfbc-d48f2e55afd4", "9ceb6a079746a67defdadd7ad19a4c9e070a7e5dd2d41df9fc6e3d289e8e49c4", "c429b777-c7b9-4e07-99ba-7cdf98a283c3", 1);
var api_password = "blockstack_integration_test_api_password";
var device_id = 'c429b777-c7b9-4e07-99ba-7cdf98a283c3';
var datastore_privkey = bitcoinjs.ECPair.makeRandom();
var datastore_privkey_hex = datastore_privkey.d.toBuffer().toString('hex');
var datastore_pubkey_hex = datastore_privkey.getPublicKeyBuffer().toString('hex');
var datastore_id = datastoreGetId(datastore_pubkey_hex);
var res = null;
var datastore = null;
var datastore_str = null;
var session_token = null;
console.log(`private key is ${datastore_privkey_hex}`);
console.log(`public key is ${datastore_pubkey_hex}`);
console.log("begin ping");
node_ping('localhost', 16268)
.then((res) => {
console.log(`ping result: ${JSON.stringify(res)}`);
var auth_request = makeAuthRequest(datastore_privkey_hex, "https://www.foo.com", "https://www.foo.com/manifest.json", "https://www.foo.com/login", ['store_read', 'store_write', 'store_admin']);
return getCoreSession('localhost', 16268, api_password, datastore_privkey_hex, "judecn.id", auth_request);
}, (error) => {console.log(JSON.stringify(error)); process.exit(1);})
.then((token_res) => {
console.log(`session result: ${JSON.stringify(token_res)}`);
session_token = token_res;
if( !session_token ) {
console.log("failed to authenticate");
process.exit(1);
}
return getOrCreateDatastore({'local': 1}, session_token, datastore_privkey_hex);
}, (error) => {console.log("get session token failed:"); console.log(error); console.log(JSON.stringify(error)); process.exit(1);})
.then((res) => {
console.log(`getOrCreateDatastore (create) result: ${JSON.stringify(res)}`);
if( res.error ) {
console.log(res);
process.exit(1);
}
// make sure it's idempotent
return getOrCreateDatastore({'local': 1}, session_token, datastore_privkey_hex);
}, (error) => {console.log("getOrCreateDatastore (create) failed:"); console.log(error); console.log(JSON.stringify(error)); process.exit(1);})
.then((res) => {
console.log(`getOrCreateDatastore (get) result: ${JSON.stringify(res)}`);
if( res.error ) {
console.log(res);
console.log("exiting");
process.exit(1);
}
datastore = res.datastore;
datastore_str = JSON.stringify(res);
return datastoreMkdir(datastore_str, '/dir1');
}, (error) => {console.log("getOrCreateDatastore (get) failed:"); console.log(error); console.log(JSON.stringify(error)); process.exit(1);})
.then((res) => {
console.log(`datastoreMkdir result: ${JSON.stringify(res)}`);
if( res.error ) {
console.log(res);
console.log(JSON.stringify(res.error));
console.log("exiting");
process.exit(1);
}
return datastoreMkdir(datastore_str, '/dir1/dir2');
}, (error) => {console.log("mkdir /dir1 failed:"); console.log(error); console.log(JSON.stringify(error)); process.exit(1);})
.then((res) => {
console.log(`datastoreMkdir result: ${JSON.stringify(res)}`);
if( res.error ) {
console.log(res);
process.exit(1);
}
return datastorePutFile(datastore_str, '/file1', "hello world");
}, (error) => {console.log("mkdir /dir1/dir2 failed:"); console.log(error); console.log(JSON.stringify(error)); process.exit(1);})
.then((res) => {
console.log(`datastorePutFile result: ${JSON.stringify(res)}`);
if( res.error ) {
console.log(res);
process.exit(1);
}
return datastorePutFile(datastore_str, '/dir1/file2', "hello world 2");
}, (error) => {console.log("putfile /file1 failed:"); console.log(error); console.log(JSON.stringify(error)); process.exit(1);})
.then((res) => {
console.log(`datastorePutFile result: ${JSON.stringify(res)}`);
if( res.error ) {
console.log(res);
process.exit(1);
}
return datastorePutFile(datastore_str, '/dir1/dir2/file3', 'hello world 3');
}, (error) => {console.log("putfile /dir1/file2 failed:"); console.log(error); console.log(JSON.stringify(error)); process.exit(1);})
.then((res) => {
console.log(`datastorePutFile result: ${JSON.stringify(res)}`);
if( res.error ) {
console.log(res);
process.exit(1);
}
return datastoreListdir(datastore_str, '/');
}, (error) => {console.log("putfile /dir1/dir2/file3 failed:"); console.log(error); console.log(JSON.stringify(error)); process.exit(1);})
.then((res) => {
console.log(`datastoreListdir result: ${JSON.stringify(res)}`);
if( !res || res.error) {
console.log(res);
process.exit(1);
}
if( !dir_expect(res, ['dir1', 'file1']) ) {
console.log("Missing dir1 or file1");
console.log(res);
process.exit(1);
}
return datastoreListdir(datastore_str, '/dir1');
}, (error) => {console.log("listdir / failed:"); console.log(error); console.log(JSON.stringify(error)); process.exit(1);})
.then((res) => {
console.log(`datastoreListdir result: ${JSON.stringify(res)}`);
if( !res || res.error) {
console.log(res);
process.exit(1);
}
if( !dir_expect(res, ['dir2', 'file2']) ) {
console.log("Missing dir2 or file2");
console.log(res);
process.exit(1);
}
return stat_dir(datastore_str, '/');
}, (error) => {console.log("listdir /dir1 failed:"); console.log(error); console.log(JSON.stringify(error)); process.exit(1);})
.then((res) => {
console.log(`stat_dir result: ${JSON.stringify(res)}`);
if( !res ) {
process.exit(1);
}
return stat_dir(datastore_str, '/dir1');
}, (error) => {console.log("stat dir / failed:"); console.log(error); console.log(JSON.stringify(error)); process.exit(1);})
.then((res) => {
console.log(`stat_dir result: ${JSON.stringify(res)}`);
if( !res ) {
process.exit(1);
}
return stat_dir(datastore_str, '/dir1/dir2');
}, (error) => {console.log("stat dir /dir1 failed:"); console.log(error); console.log(JSON.stringify(error)); process.exit(1);})
.then((res) => {
console.log(`stat_dir result: ${JSON.stringify(res)}`);
if( !res ) {
process.exit(1);
}
return stat_file(datastore_str, '/file1');
}, (error) => {console.log("stat dir /dir1/dir2 failed:"); console.log(error); console.log(JSON.stringify(error)); process.exit(1);})
.then((res) => {
console.log(`stat_file result: ${JSON.stringify(res)}`);
if( !res ) {
process.exit(1);
}
return stat_file(datastore_str, '/dir1/file2');
}, (error) => {console.log("stat file /file1 failed:"); console.log(error); console.log(JSON.stringify(error)); process.exit(1);})
.then((res) => {
console.log(`stat_file result: ${JSON.stringify(res)}`);
if( !res ) {
process.exit(1);
}
return stat_file(datastore_str, '/dir1/dir2/file3');
}, (error) => {console.log("stat file /dir1/file2 failed:"); console.log(error); console.log(JSON.stringify(error)); process.exit(1);})
.then((res) => {
console.log(`stat_file result: ${JSON.stringify(res)}`);
if( !res ) {
process.exit(1);
}
return file_expect(datastore_str, '/file1', 'hello world');
}, (error) => {console.log("stat file /dir1/dir2/file3 failed:"); console.log(error); console.log(JSON.stringify(error)); process.exit(1);})
.then((res) => {
console.log(`file_expect result: ${JSON.stringify(res)}`);
if( !res ) {
process.exit(1);
}
return file_expect(datastore_str, '/dir1/file2', 'hello world 2');
}, (error) => {console.log("get file /file1 failed:"); console.log(error); console.log(JSON.stringify(error)); process.exit(1);})
.then((res) => {
console.log(`file_expect result: ${JSON.stringify(res)}`);
if( !res ) {
process.exit(1);
}
return file_expect(datastore_str, '/dir1/dir2/file3', 'hello world 3');
}, (error) => {console.log("get file /dir1/file2 failed:"); console.log(error); console.log(JSON.stringify(error)); process.exit(1);})
.then((res) => {
console.log(`file_expect result: ${JSON.stringify(res)}`);
if( !res || res.error) {
process.exit(1);
}
return datastoreDeleteFile(datastore_str, '/file1');
}, (error) => {console.log("get file /dir1/dir2/file3 failed:"); console.log(error); console.log(JSON.stringify(error)); process.exit(1);})
.then((res) => {
console.log(`deletefile result: ${JSON.stringify(res)}`);
if( !res || res.error) {
process.exit(1);
}
return datastoreDeleteFile(datastore_str, '/dir1/file2');
}, (error) => {console.log("delete file /file1 failed:"); console.log(error); console.log(JSON.stringify(error)); process.exit(1);})
.then((res) => {
console.log(`deletefile result: ${JSON.stringify(res)}`);
if( !res || res.error ) {
process.exit(1);
}
return datastoreDeleteFile(datastore_str, '/dir1/dir2/file3');
}, (error) => {console.log("delete file /dir1/file2 failed:"); console.log(error); console.log(JSON.stringify(error)); process.exit(1);})
.then((res) => {
console.log(`deletefile result: ${JSON.stringify(res)}`);
if( !res || res.error ) {
process.exit(1);
}
return stat_file(datastore_str, '/file1', true);
}, (error) => {console.log("delete file /dir1/dir2/file3 failed:"); console.log(error); console.log(JSON.stringify(error)); process.exit(1);})
.then((res) => {
console.log(`stat_file result (expect failure): ${JSON.stringify(res)}`);
if( !res || res.error) {
process.exit(1);
}
return stat_file(datastore_str, '/dir1/file2', true);
}, (error) => {console.log("stat /file1 failed:"); console.log(error); console.log(JSON.stringify(error)); process.exit(1);})
.then((res) => {
console.log(`stat_file result (expect failure): ${JSON.stringify(res)}`);
if( !res || res.error ) {
process.exit(1);
}
return stat_file(datastore_str, '/dir1/dir2/file3', true);
}, (error) => {console.log("stat file /dir1/file2 failed:"); console.log(error); console.log(JSON.stringify(error)); process.exit(1);})
.then((res) => {
console.log(`stat_file result: ${JSON.stringify(res)}`);
if( !res || res.error ) {
process.exit(1);
}
return file_absent(datastore_str, '/file1');
}, (error) => {console.log("stat file /dir1/dir2/file3 failed:"); console.log(error); console.log(JSON.stringify(error)); process.exit(1);})
.then((res) => {
console.log(`file_absent result (expect failure): ${JSON.stringify(res)}`);
if( !res || res.error) {
process.exit(1);
}
return file_absent(datastore_str, '/dir1/file2');
}, (error) => {console.log("getFile /dir1/file2 failed:"); console.log(error); console.log(JSON.stringify(error)); process.exit(1);})
.then((res) => {
console.log(`file_absent result (expect failure): ${JSON.stringify(res)}`);
if( !res || res.error ) {
process.exit(1);
}
return file_absent(datastore_str, '/dir1/dir2/file3', true);
}, (error) => {console.log("getFile /dir1/file2 failed:"); console.log(error); console.log(JSON.stringify(error)); process.exit(1);})
.then((res) => {
console.log(`file_absent result (expect failure): ${JSON.stringify(res)}`);
if( !res || res.error ) {
process.exit(1);
}
return datastoreRmdir(datastore_str, '/dir1/dir2');
}, (error) => {console.log("getFile /dir1/dir2/file3 failed:"); console.log(error); console.log(JSON.stringify(error)); process.exit(1);})
.then((res) => {
console.log(`rmdir result: ${JSON.stringify(res)}`);
if( !res || res.error ) {
process.exit(1);
}
return datastoreRmdir(datastore_str, '/dir1');
}, (error) => {console.log("rmdir /dir1/dir2 failed:"); console.log(error); console.log(JSON.stringify(error)); process.exit(1);})
.then((res) => {
console.log(`rmdir result: ${JSON.stringify(res)}`);
if( res.error ) {
console.log(res);
process.exit(1);
}
return dir_absent(datastore_str, '/dir1/dir2');
}, (error) => {console.log("rmdir /dir1 failed:"); console.log(error); console.log(JSON.stringify(error)); process.exit(1);})
.then((res) => {
console.log(`dir_absent result: ${JSON.stringify(res)}`);
if( !res || res.error) {
console.log(res);
process.exit(1);
}
return dir_absent(datastore_str, '/dir1');
}, (error) => {console.log("listdir /dir1/dir2 failed:"); console.log(error); console.log(JSON.stringify(error)); process.exit(1);})
.then((res) => {
console.log(`dir_absent result: ${JSON.stringify(res)}`);
if( !res || res.error) {
console.log(res);
process.exit(1);
}
return stat_dir(datastore_str, '/dir1', true);
}, (error) => {console.log("listdir /dir1 failed:"); console.log(error); console.log(JSON.stringify(error)); process.exit(1);})
.then((res) => {
console.log(`stat_dir result: ${JSON.stringify(res)}`);
if( !res || res.error ) {
process.exit(1);
}
return stat_dir(datastore_str, '/dir1/dir2', true);
}, (error) => {console.log("stat dir /dir1 failed:"); console.log(error); console.log(JSON.stringify(error)); process.exit(1);})
.then((res) => {
console.log(`stat_dir result: ${JSON.stringify(res)}`);
if( !res || res.error ) {
process.exit(1);
}
return deleteDatastore(datastore_str);
}, (error) => {console.log("stat dir /dir1/dir2 failed:"); console.log(error); console.log(JSON.stringify(error)); process.exit(1);})
.then((res) => {
console.log(`delete datastore result: ${JSON.stringify(res)}`);
if( !res ) {
process.exit(1);
}
process.exit(0);
}, (error) => {console.log("delete datastore failed:"); console.log(error); console.log(JSON.stringify(error)); process.exit(1);});
}
else {
console.log("No command given");
console.log(`args = ${args}`);
console.log(`command = ${command}`);
assert(0);
}