2017-04-17 14:46:39 +02:00
/* global it:false */
/* global describe:false */
/* global before:false */
/* global after:false */
2021-08-19 13:24:38 -07:00
/* global xit:false */
2017-04-17 14:46:39 +02:00
'use strict' ;
2023-08-04 11:24:28 +05:30
const backups = require ( '../backups.js' ) ,
BoxError = require ( '../boxerror.js' ) ,
2021-07-14 19:03:12 -07:00
common = require ( './common.js' ) ,
2018-08-02 14:59:50 -07:00
execSync = require ( 'child_process' ) . execSync ,
2017-09-27 10:25:36 -07:00
expect = require ( 'expect.js' ) ,
filesystem = require ( '../storage/filesystem.js' ) ,
2017-04-17 14:46:39 +02:00
fs = require ( 'fs' ) ,
2022-04-15 08:07:46 -05:00
gcs = require ( '../storage/gcs.js' ) ,
2017-10-02 20:08:00 -07:00
noop = require ( '../storage/noop.js' ) ,
2017-04-17 14:46:39 +02:00
os = require ( 'os' ) ,
path = require ( 'path' ) ,
2017-09-17 17:51:00 +02:00
s3 = require ( '../storage/s3.js' ) ,
2024-07-08 22:29:45 +02:00
safe = require ( 'safetydance' ) ,
stream = require ( 'stream/promises' ) ;
2017-04-17 14:46:39 +02:00
2022-04-15 09:25:54 -05:00
const chunk = s3 . _chunk ;
2017-04-17 14:46:39 +02:00
describe ( 'Storage' , function ( ) {
2021-07-14 19:03:12 -07:00
const { setup , cleanup } = common ;
before ( setup ) ;
after ( cleanup ) ;
2017-10-02 20:08:00 -07:00
2021-07-14 19:03:12 -07:00
describe ( 'filesystem' , function ( ) {
let gTmpFolder ;
2017-10-02 20:08:00 -07:00
2021-07-14 19:03:12 -07:00
const gBackupConfig = {
2017-04-17 14:46:39 +02:00
provider : 'filesystem' ,
key : 'key' ,
2017-09-23 14:27:35 -07:00
backupFolder : null ,
2021-07-14 19:03:12 -07:00
format : 'tgz' ,
2017-04-17 14:46:39 +02:00
} ;
before ( function ( done ) {
2017-10-02 20:08:00 -07:00
gTmpFolder = fs . mkdtempSync ( path . join ( os . tmpdir ( ) , 'filesystem-storage-test_' ) ) ;
2017-04-17 14:46:39 +02:00
2017-10-02 20:08:00 -07:00
gBackupConfig . backupFolder = path . join ( gTmpFolder , 'backups/' ) ;
2017-04-17 14:46:39 +02:00
2017-10-02 20:08:00 -07:00
done ( ) ;
} ) ;
2017-04-17 14:46:39 +02:00
2017-10-02 20:08:00 -07:00
after ( function ( done ) {
2022-11-06 11:48:56 +01:00
fs . rmSync ( gTmpFolder , { recursive : true , force : true } ) ;
2017-10-02 20:08:00 -07:00
done ( ) ;
} ) ;
2017-09-20 09:57:16 -07:00
2023-08-15 20:24:54 +05:30
it ( 'fails to set backup storage for bad folder' , async function ( ) {
2021-07-14 19:03:12 -07:00
const tmp = Object . assign ( { } , gBackupConfig , { backupFolder : '/root/oof' } ) ;
2023-08-15 20:24:54 +05:30
const [ error ] = await safe ( backups . setStorage ( tmp ) ) ;
2021-08-19 13:24:38 -07:00
expect ( error . reason ) . to . equal ( BoxError . BAD _FIELD ) ;
2021-07-14 19:03:12 -07:00
} ) ;
2023-08-15 20:24:54 +05:30
it ( 'succeeds to set backup storage' , async function ( ) {
await backups . setStorage ( gBackupConfig ) ;
2021-08-19 13:24:38 -07:00
expect ( fs . existsSync ( path . join ( gBackupConfig . backupFolder , 'snapshot' ) ) ) . to . be ( true ) ; // auto-created
2021-07-14 19:03:12 -07:00
} ) ;
2024-07-08 22:29:45 +02:00
it ( 'can upload' , async function ( ) {
2022-04-14 17:41:41 -05:00
const sourceFile = path . join ( _ _dirname , 'storage/data/test.txt' ) ;
const sourceStream = fs . createReadStream ( sourceFile ) ;
const destFile = gTmpFolder + '/uploadtest/test.txt' ;
2024-07-08 22:29:45 +02:00
const uploader = await filesystem . upload ( gBackupConfig , destFile ) ;
await stream . pipeline ( sourceStream , uploader . stream ) ;
await uploader . finish ( ) ;
expect ( fs . existsSync ( destFile ) ) ;
expect ( fs . statSync ( sourceFile ) . size ) . to . be ( fs . statSync ( destFile ) . size ) ;
2017-04-17 14:46:39 +02:00
} ) ;
2017-04-18 17:34:42 +02:00
2024-07-08 22:29:45 +02:00
it ( 'upload waits for empty file to be created' , async function ( ) {
2022-04-14 17:41:41 -05:00
const sourceFile = path . join ( _ _dirname , 'storage/data/empty' ) ;
const sourceStream = fs . createReadStream ( sourceFile ) ;
const destFile = gTmpFolder + '/uploadtest/empty' ;
2024-07-08 22:29:45 +02:00
const uploader = await filesystem . upload ( gBackupConfig , destFile ) ;
await stream . pipeline ( sourceStream , uploader . stream ) ;
await uploader . finish ( ) ;
expect ( fs . existsSync ( destFile ) ) ;
expect ( fs . statSync ( sourceFile ) . size ) . to . be ( fs . statSync ( destFile ) . size ) ;
2017-04-21 17:21:10 +02:00
} ) ;
2024-07-08 22:29:45 +02:00
it ( 'upload unlinks old file' , async function ( ) {
2022-04-14 17:41:41 -05:00
const sourceFile = path . join ( _ _dirname , 'storage/data/test.txt' ) ;
const sourceStream = fs . createReadStream ( sourceFile ) ;
const destFile = gTmpFolder + '/uploadtest/test.txt' ;
const oldStat = fs . statSync ( destFile ) ;
2024-07-08 22:29:45 +02:00
const uploader = await filesystem . upload ( gBackupConfig , destFile ) ;
await stream . pipeline ( sourceStream , uploader . stream ) ;
await uploader . finish ( ) ;
expect ( fs . existsSync ( destFile ) ) . to . be ( true ) ;
expect ( fs . statSync ( sourceFile ) . size ) . to . be ( fs . statSync ( destFile ) . size ) ;
expect ( oldStat . inode ) . to . not . be ( fs . statSync ( destFile ) . size ) ;
2017-04-21 17:21:10 +02:00
} ) ;
2023-07-28 13:15:08 +05:30
it ( 'can download file' , async function ( ) {
2022-04-14 17:41:41 -05:00
const sourceFile = gTmpFolder + '/uploadtest/test.txt' ;
2017-04-21 17:21:10 +02:00
2023-07-28 13:15:08 +05:30
const [ error , stream ] = await safe ( filesystem . download ( gBackupConfig , sourceFile ) ) ;
expect ( error ) . to . be ( null ) ;
expect ( stream ) . to . be . an ( 'object' ) ;
2017-04-17 14:46:39 +02:00
} ) ;
2023-07-28 13:15:08 +05:30
it ( 'download errors for missing file' , async function ( ) {
2022-04-14 17:41:41 -05:00
const sourceFile = gTmpFolder + '/uploadtest/missing' ;
2017-04-17 14:46:39 +02:00
2023-07-28 13:15:08 +05:30
const [ error ] = await safe ( filesystem . download ( gBackupConfig , sourceFile ) ) ;
expect ( error . reason ) . to . be ( BoxError . NOT _FOUND ) ;
2017-04-17 14:46:39 +02:00
} ) ;
2025-02-12 18:46:54 +01:00
it ( 'list dir lists the source dir' , async function ( ) {
2022-04-14 17:41:41 -05:00
const sourceDir = path . join ( _ _dirname , 'storage' ) ;
2017-04-17 14:46:39 +02:00
2025-02-12 18:46:54 +01:00
let allFiles = [ ] , marker = null ;
while ( true ) {
const result = await filesystem . listDir ( gBackupConfig , sourceDir , 1 , marker ) ;
allFiles = allFiles . concat ( result . entries ) ;
if ( ! result . marker ) break ;
marker = result . marker ;
}
2018-08-02 14:59:50 -07:00
2025-02-12 18:46:54 +01:00
const expectedFiles = execSync ( ` find ${ sourceDir } -type f ` , { encoding : 'utf8' } ) . trim ( ) . split ( '\n' ) ;
expect ( allFiles . map ( function ( f ) { return f . fullPath ; } ) . sort ( ) ) . to . eql ( expectedFiles . sort ( ) ) ;
2017-10-02 20:08:00 -07:00
} ) ;
2017-04-21 17:21:10 +02:00
2022-04-30 16:01:42 -07:00
it ( 'can copy' , async function ( ) {
2022-04-14 17:41:41 -05:00
const sourceFile = gTmpFolder + '/uploadtest/test.txt' ; // keep the test within save device
const destFile = gTmpFolder + '/uploadtest/test-hardlink.txt' ;
2017-09-20 09:57:16 -07:00
2022-04-30 16:01:42 -07:00
await filesystem . copy ( gBackupConfig , sourceFile , destFile , ( ) => { } ) ;
expect ( fs . statSync ( destFile ) . nlink ) . to . be ( 2 ) ; // created a hardlink
2017-04-17 14:46:39 +02:00
} ) ;
2022-04-14 20:43:04 -05:00
it ( 'can remove file' , async function ( ) {
2022-04-14 17:41:41 -05:00
const sourceFile = gTmpFolder + '/uploadtest/test-hardlink.txt' ;
2017-04-17 14:46:39 +02:00
2022-04-14 20:43:04 -05:00
await filesystem . remove ( gBackupConfig , sourceFile ) ;
expect ( fs . existsSync ( sourceFile ) ) . to . be ( false ) ;
2017-04-17 14:46:39 +02:00
} ) ;
2022-04-14 20:43:04 -05:00
it ( 'can remove empty dir' , async function ( ) {
2022-04-14 17:41:41 -05:00
const sourceDir = gTmpFolder + '/emptydir' ;
2017-10-02 20:08:00 -07:00
fs . mkdirSync ( sourceDir ) ;
2017-09-20 09:57:16 -07:00
2022-04-14 20:43:04 -05:00
await filesystem . remove ( gBackupConfig , sourceDir , ( ) => { } ) ;
expect ( fs . existsSync ( sourceDir ) ) . to . be ( false ) ;
2017-04-17 14:46:39 +02:00
} ) ;
2017-10-02 20:08:00 -07:00
} ) ;
2017-04-17 14:46:39 +02:00
2017-10-02 20:08:00 -07:00
describe ( 'noop' , function ( ) {
2022-04-14 17:41:41 -05:00
const gBackupConfig = {
2017-10-02 20:08:00 -07:00
provider : 'noop' ,
format : 'tgz'
} ;
2024-08-27 15:16:18 +02:00
it ( 'upload works' , async function ( ) {
await noop . upload ( gBackupConfig , 'file' , { } ) ;
2017-10-02 20:08:00 -07:00
} ) ;
2017-04-17 14:46:39 +02:00
2023-07-28 13:15:08 +05:30
it ( 'can download file' , async function ( ) {
const [ error ] = await safe ( noop . download ( gBackupConfig , 'file' ) ) ;
expect ( error ) . to . be . an ( Error ) ;
2017-10-02 20:08:00 -07:00
} ) ;
2017-04-21 17:21:10 +02:00
2025-02-12 18:46:54 +01:00
it ( 'list dir contents of source dir' , async function ( ) {
const result = await noop . listDir ( gBackupConfig , 'sourceDir' , 1000 , null /* marker */ ) ;
expect ( result . marker ) . to . be ( null ) ;
expect ( result . entries ) . to . eql ( [ ] ) ;
2017-10-02 20:08:00 -07:00
} ) ;
2017-04-21 17:21:10 +02:00
2022-04-30 16:01:42 -07:00
it ( 'can copy' , async function ( ) {
await noop . copy ( gBackupConfig , 'sourceFile' , 'destFile' , ( ) => { } ) ;
2017-10-02 20:08:00 -07:00
} ) ;
2017-09-20 09:57:16 -07:00
2022-04-14 20:43:04 -05:00
it ( 'can remove file' , async function ( ) {
await noop . remove ( gBackupConfig , 'sourceFile' ) ;
2017-04-17 14:46:39 +02:00
} ) ;
2022-04-14 20:43:04 -05:00
it ( 'can remove empty dir' , async function ( ) {
2025-02-12 20:56:46 +01:00
await noop . remove ( gBackupConfig , 'sourceDir' ) ;
2017-04-17 14:46:39 +02:00
} ) ;
} ) ;
2017-04-18 17:34:42 +02:00
describe ( 's3' , function ( ) {
2025-02-12 20:56:46 +01:00
const basePath = path . join ( os . tmpdir ( ) , 's3-backup-test-buckets' ) ;
const backupConfig = {
2017-04-18 17:34:42 +02:00
provider : 's3' ,
key : 'key' ,
prefix : 'unit.test' ,
bucket : 'cloudron-storage-test' ,
2017-04-18 19:15:56 +02:00
accessKeyId : 'testkeyid' ,
secretAccessKey : 'testsecret' ,
2017-09-23 14:27:35 -07:00
region : 'eu-central-1' ,
format : 'tgz'
2017-04-18 17:34:42 +02:00
} ;
2025-02-12 20:56:46 +01:00
const bucketPath = path . join ( basePath , backupConfig . bucket ) ;
class S3MockUpload {
constructor ( args ) { // { client: s3, params, partSize, queueSize: 3, leavePartsOnError: false }
console . log ( basePath , args . params . Bucket , args . params . Key ) ;
const destFilePath = path . join ( basePath , args . params . Bucket , args . params . Key ) ;
fs . mkdirSync ( path . dirname ( destFilePath ) , { recursive : true } ) ;
this . pipeline = stream . pipeline ( args . params . Body , fs . createWriteStream ( destFilePath ) ) ;
console . log ( destFilePath ) ;
}
2017-04-18 17:34:42 +02:00
2025-02-12 20:56:46 +01:00
on ( ) { }
async done ( ) {
await this . pipeline ;
}
}
class S3Mock {
constructor ( cfg ) {
expect ( cfg . credentials ) . to . eql ( { // retryDelayOptions is a function
accessKeyId : backupConfig . accessKeyId ,
secretAccessKey : backupConfig . secretAccessKey
} ) ;
expect ( cfg . region ) . to . be ( backupConfig . region ) ;
}
2025-06-06 08:34:21 +02:00
async listObjectsV2 ( params ) {
2025-02-12 20:56:46 +01:00
expect ( params . Bucket ) . to . be ( backupConfig . bucket ) ;
return {
Contents : [ {
Key : 'uploadtest/test.txt' ,
Size : 23
} , {
Key : 'uploadtest/C++.gitignore' ,
Size : 23
} ]
} ;
}
2017-04-18 19:15:56 +02:00
2025-02-12 20:56:46 +01:00
async copyObject ( params ) {
console . log ( path . join ( basePath , params . CopySource ) , path . join ( bucketPath , params . Key ) ) ;
await fs . promises . mkdir ( path . dirname ( path . join ( bucketPath , params . Key ) ) , { recursive : true } ) ;
await fs . promises . copyFile ( path . join ( basePath , params . CopySource . replace ( /%2B/g , '+' ) ) , path . join ( bucketPath , params . Key ) ) ; // CopySource already has the bucket path!
}
async deleteObjects ( params ) {
expect ( params . Bucket ) . to . be ( backupConfig . bucket ) ;
params . Delete . Objects . forEach ( o => fs . rmSync ( path . join ( bucketPath , o . Key ) ) ) ;
}
}
before ( function ( ) {
fs . rmSync ( basePath , { recursive : true , force : true } ) ;
globalThis . S3Mock = S3Mock ;
globalThis . S3MockUpload = S3MockUpload ;
2017-04-18 17:34:42 +02:00
} ) ;
2017-10-02 20:08:00 -07:00
after ( function ( ) {
2025-02-12 20:56:46 +01:00
// fs.rmSync(basePath, { recursive: true, force: true });
delete globalThis . S3Mock ;
delete globalThis . S3MockUpload ;
2017-10-02 20:08:00 -07:00
} ) ;
2017-04-18 19:15:56 +02:00
2024-07-08 22:29:45 +02:00
it ( 'can upload' , async function ( ) {
2022-04-14 17:41:41 -05:00
const sourceFile = path . join ( _ _dirname , 'storage/data/test.txt' ) ;
const sourceStream = fs . createReadStream ( sourceFile ) ;
const destKey = 'uploadtest/test.txt' ;
2025-02-12 20:56:46 +01:00
const uploader = await s3 . upload ( backupConfig , destKey ) ;
2024-07-08 22:29:45 +02:00
await stream . pipeline ( sourceStream , uploader . stream ) ;
await uploader . finish ( ) ;
2025-02-12 20:56:46 +01:00
expect ( fs . existsSync ( path . join ( bucketPath , destKey ) ) ) . to . be ( true ) ;
expect ( fs . statSync ( path . join ( bucketPath , destKey ) ) . size ) . to . be ( fs . statSync ( sourceFile ) . size ) ;
2017-04-18 17:34:42 +02:00
} ) ;
2023-07-28 13:15:08 +05:30
it ( 'can download file' , async function ( ) {
2022-04-14 17:41:41 -05:00
const sourceKey = 'uploadtest/test.txt' ;
2025-02-12 20:56:46 +01:00
const [ error , outstream ] = await safe ( s3 . download ( backupConfig , sourceKey ) ) ;
2023-07-28 13:15:08 +05:30
expect ( error ) . to . be ( null ) ;
2025-02-12 20:56:46 +01:00
expect ( outstream ) . to . be . an ( 'object' ) ;
2017-04-18 17:34:42 +02:00
} ) ;
2025-02-12 18:46:54 +01:00
it ( 'list dir lists contents of source dir' , async function ( ) {
let allFiles = [ ] , marker = null ;
while ( true ) {
2025-02-12 20:56:46 +01:00
const result = await s3 . listDir ( backupConfig , '' , 1 , marker ) ;
2025-02-12 18:46:54 +01:00
allFiles = allFiles . concat ( result . entries ) ;
if ( ! result . marker ) break ;
marker = result . marker ;
}
2017-04-21 17:21:10 +02:00
2025-02-12 20:56:46 +01:00
expect ( allFiles . map ( function ( f ) { return f . fullPath ; } ) ) . to . contain ( 'uploadtest/test.txt' ) ;
2017-04-18 17:34:42 +02:00
} ) ;
2022-04-30 16:01:42 -07:00
it ( 'can copy' , async function ( ) {
2025-02-12 20:56:46 +01:00
fs . writeFileSync ( path . join ( bucketPath , 'uploadtest/C++.gitignore' ) , 'special' , 'utf8' ) ;
2017-10-03 15:40:01 -07:00
2025-02-12 20:56:46 +01:00
await s3 . copy ( backupConfig , 'uploadtest' , 'uploadtest-copy' , ( ) => { } ) ;
2022-04-30 16:01:42 -07:00
const sourceFile = path . join ( _ _dirname , 'storage/data/test.txt' ) ;
2025-02-12 20:56:46 +01:00
expect ( fs . statSync ( path . join ( bucketPath , 'uploadtest-copy/test.txt' ) ) . size ) . to . be ( fs . statSync ( sourceFile ) . size ) ;
expect ( fs . statSync ( path . join ( bucketPath , 'uploadtest-copy/C++.gitignore' ) ) . size ) . to . be ( 7 ) ;
2017-04-18 17:34:42 +02:00
} ) ;
2024-07-08 22:29:45 +02:00
it ( 'can remove file' , async function ( ) {
2025-02-12 20:56:46 +01:00
await s3 . remove ( backupConfig , 'uploadtest/test.txt' ) ;
expect ( fs . existsSync ( path . join ( bucketPath , 'uploadtest/test.txt' ) ) ) . to . be ( false ) ;
2017-04-18 17:34:42 +02:00
} ) ;
2025-02-12 20:56:46 +01:00
it ( 'cannot remove non-existent file' , async function ( ) {
const [ error ] = await safe ( s3 . remove ( backupConfig , 'blah' ) ) ;
expect ( error ) . to . be . ok ( ) ;
2017-04-18 17:34:42 +02:00
} ) ;
} ) ;
2017-09-17 17:51:00 +02:00
describe ( 'gcs' , function ( ) {
2022-04-14 17:41:41 -05:00
const gBackupConfig = {
2017-09-17 17:51:00 +02:00
provider : 'gcs' ,
key : '' ,
prefix : 'unit.test' ,
bucket : 'cloudron-storage-test' ,
2025-02-12 20:56:46 +01:00
projectId : 'some-project' ,
2017-09-17 17:51:00 +02:00
credentials : {
2025-02-12 20:56:46 +01:00
client _email : 'some-client' ,
private _key : 'some-key'
2017-09-17 17:51:00 +02:00
}
} ;
2025-02-12 20:56:46 +01:00
2022-04-14 17:41:41 -05:00
const GCSMockBasePath = path . join ( os . tmpdir ( ) , 'gcs-backup-test-buckets/' ) ;
2025-02-12 20:56:46 +01:00
class GCSMockBucket {
constructor ( name ) {
expect ( name ) . to . be ( gBackupConfig . bucket ) ;
}
file ( filename ) {
function ensurePathWritable ( filename ) {
filename = GCSMockBasePath + filename ;
fs . mkdirSync ( path . dirname ( filename ) , { recursive : true } ) ;
return filename ;
}
2017-09-17 17:51:00 +02:00
2022-04-14 20:43:04 -05:00
return {
2025-02-12 20:56:46 +01:00
name : filename ,
createReadStream : function ( ) {
return fs . createReadStream ( ensurePathWritable ( filename ) )
. on ( 'error' , function ( e ) {
console . log ( 'error createReadStream: ' + filename ) ;
if ( e . code == 'ENOENT' ) { e . code = 404 ; }
this . emit ( 'error' , e ) ;
} ) ;
} ,
createWriteStream : function ( ) {
return fs . createWriteStream ( ensurePathWritable ( filename ) ) ;
} ,
delete : async function ( ) {
await fs . promises . unlink ( ensurePathWritable ( filename ) ) ;
} ,
copy : function ( dst , cb ) {
function notFoundHandler ( e ) {
if ( e && e . code == 'ENOENT' ) { e . code = 404 ; return cb ( e ) ; }
cb ( ) ;
}
return fs . createReadStream ( ensurePathWritable ( filename ) )
. on ( 'end' , cb )
. on ( 'error' , notFoundHandler )
. pipe ( fs . createWriteStream ( ensurePathWritable ( dst ) ) )
. on ( 'end' , cb )
. on ( 'error' , notFoundHandler ) ;
}
} ;
}
async getFiles ( q ) {
const target = path . join ( GCSMockBasePath , q . prefix ) ;
const files = execSync ( ` find ${ target } -type f ` , { encoding : 'utf8' } ) . trim ( ) . split ( '\n' ) ;
const pageToken = q . pageToken || 0 ;
const chunkedFiles = chunk ( files , q . maxResults ) ;
if ( q . pageToken >= chunkedFiles . length ) return [ [ ] , null ] ;
const gFiles = chunkedFiles [ pageToken ] . map ( f => {
return this . file ( path . relative ( GCSMockBasePath , f ) ) ;
} ) ;
q . pageToken = pageToken + 1 ;
return [ gFiles , q . pageToken < chunkedFiles . length ? q : null ] ;
}
} ;
class GCSMock {
constructor ( config ) {
expect ( config . projectId ) . to . be ( gBackupConfig . projectId ) ;
expect ( config . credentials . private _key ) . to . be ( gBackupConfig . credentials . private _key ) ;
}
bucket ( name ) {
return new GCSMockBucket ( name ) ;
}
}
before ( function ( ) {
globalThis . GCSMock = GCSMock ;
2017-09-17 17:51:00 +02:00
} ) ;
2025-02-12 20:56:46 +01:00
after ( function ( ) {
2022-11-06 11:48:56 +01:00
fs . rmSync ( GCSMockBasePath , { recursive : true , force : true } ) ;
2025-02-12 20:56:46 +01:00
delete globalThis . GCSMock ;
2017-09-17 17:51:00 +02:00
} ) ;
2024-07-08 22:29:45 +02:00
it ( 'can backup' , async function ( ) {
2022-04-14 17:41:41 -05:00
const sourceFile = path . join ( _ _dirname , 'storage/data/test.txt' ) ;
const sourceStream = fs . createReadStream ( sourceFile ) ;
const destKey = 'uploadtest/test.txt' ;
2024-07-08 22:29:45 +02:00
const uploader = await gcs . upload ( gBackupConfig , destKey ) ;
await stream . pipeline ( sourceStream , uploader . stream ) ;
await uploader . finish ( ) ;
2017-09-17 17:51:00 +02:00
} ) ;
2023-07-28 13:15:08 +05:30
it ( 'can download file' , async function ( ) {
2022-04-14 17:41:41 -05:00
const sourceKey = 'uploadtest/test.txt' ;
2023-07-28 13:15:08 +05:30
const [ error , stream ] = await safe ( gcs . download ( gBackupConfig , sourceKey ) ) ;
expect ( error ) . to . be ( null ) ;
expect ( stream ) . to . be . an ( 'object' ) ;
2017-10-29 11:10:50 +01:00
} ) ;
2017-09-17 17:51:00 +02:00
2025-02-12 18:46:54 +01:00
it ( 'list dir lists contents of source dir' , async function ( ) {
let allFiles = [ ] , marker = null ;
while ( true ) {
const result = await gcs . listDir ( gBackupConfig , '' , 1 , marker ) ;
allFiles = allFiles . concat ( result . entries ) ;
if ( ! result . marker ) break ;
marker = result . marker ;
}
2017-09-17 17:51:00 +02:00
2025-02-12 18:46:54 +01:00
expect ( allFiles . map ( function ( f ) { return f . fullPath ; } ) . sort ( ) ) . to . eql ( [ 'uploadtest/test.txt' ] ) ;
2017-09-17 17:51:00 +02:00
} ) ;
2019-05-07 09:34:23 -07:00
xit ( 'can copy' , function ( done ) {
2017-10-29 11:10:50 +01:00
fs . writeFileSync ( path . join ( GCSMockBasePath , 'uploadtest/C++.gitignore' ) , 'special' , 'utf8' ) ;
2017-09-17 17:51:00 +02:00
2022-04-14 17:41:41 -05:00
const sourceKey = 'uploadtest' ;
2017-09-17 17:51:00 +02:00
2022-04-14 17:41:41 -05:00
const events = gcs . copy ( gBackupConfig , sourceKey , 'uploadtest-copy' ) ;
2017-10-29 11:10:50 +01:00
events . on ( 'done' , function ( error ) {
2022-04-14 17:41:41 -05:00
const sourceFile = path . join ( _ _dirname , 'storage/data/test.txt' ) ;
2017-10-29 11:10:50 +01:00
expect ( error ) . to . be ( null ) ;
expect ( fs . statSync ( path . join ( GCSMockBasePath , 'uploadtest-copy/test.txt' ) ) . size ) . to . be ( fs . statSync ( sourceFile ) . size ) ;
expect ( fs . statSync ( path . join ( GCSMockBasePath , 'uploadtest-copy/C++.gitignore' ) ) . size ) . to . be ( 7 ) ;
2017-09-17 17:51:00 +02:00
done ( ) ;
} ) ;
} ) ;
2022-04-14 20:43:04 -05:00
it ( 'can remove file' , async function ( ) {
await gcs . remove ( gBackupConfig , 'uploadtest-copy/test.txt' ) ;
expect ( fs . existsSync ( path . join ( GCSMockBasePath , 'uploadtest-copy/test.txt' ) ) ) . to . be ( false ) ;
2017-09-17 17:51:00 +02:00
} ) ;
2022-04-14 20:43:04 -05:00
it ( 'can remove non-existent dir' , async function ( ) {
await gcs . remove ( gBackupConfig , 'blah' , ( ) => { } ) ;
2017-09-17 17:51:00 +02:00
} ) ;
} ) ;
2017-04-17 14:46:39 +02:00
} ) ;