refactor: unify image objects across GUI and image-stream (#1229)

`image-stream` returns image objects that look like this:

```js
{
  stream: <readable stream>,
  transform: <transform stream>,
  size: {
    original: <number>,
    final: {
      value: <number>,
      estimation: <boolean>
    }
  },
  ...
}
```

While the GUI handles image objects that look like this:

```sh
{
  path: <string>,
  size: <number>,
  ...
}
```

It looks like we should share a common structure between both, so we can
use `image-stream` images in `drive-constraints`, for example.

Turns out that we actually transform `image-stream` image objects to GUI
image objects when the user selects an image using the image selector
dialog, which is another indicator that we should normalise this
situation.

As a solution, this commit does the following:

- Add `path` to `image-stream` image object
- Reuse `image-stream` image objects in the GUI, given they are a
  superset of GUI image objects

See: https://github.com/resin-io/etcher/pull/1223#discussion_r108165110
Fixes: https://github.com/resin-io/etcher/issues/1232
Signed-off-by: Juan Cruz Viotti <jviotti@openmailbox.org>
This commit is contained in:
Juan Cruz Viotti 2017-04-06 09:41:08 -04:00 committed by GitHub
parent 63901ccf77
commit 802d9abb1d
20 changed files with 570 additions and 113 deletions

View File

@ -69,9 +69,7 @@ exports.writeImage = (imagePath, drive, options, onProgress) => {
return fs.openAsync(drive.raw, 'rs+');
}).then((driveFileDescriptor) => {
return imageStream.getFromFilePath(imagePath).then((image) => {
if (!image.size.final.estimation && !constraints.isDriveLargeEnough(drive, {
size: image.size.final.value
})) {
if (!constraints.isDriveLargeEnough(drive, image)) {
throw errors.createUserError(
'The image you selected is too big for this drive',
'Please connect a bigger drive and try again'

View File

@ -146,7 +146,9 @@ SelectionStateModel.service('SelectionStateModel', function(DrivesModel) {
return _.get(Store.getState().toJS(), [
'selection',
'image',
'size'
'size',
'final',
'value'
]);
};

View File

@ -287,10 +287,24 @@ const storeReducer = (state = DEFAULT_STATE, action) => {
throw errors.createError('Missing image size');
}
if (!_.isNumber(action.data.size)) {
if (!_.isPlainObject(action.data.size)) {
throw errors.createError(`Invalid image size: ${action.data.size}`);
}
const MINIMUM_IMAGE_SIZE = 0;
if (!_.isInteger(action.data.size.original) || action.data.size.original < MINIMUM_IMAGE_SIZE) {
throw errors.createError(`Invalid original image size: ${action.data.size.original}`);
}
if (!_.isInteger(action.data.size.final.value) || action.data.size.final.value < MINIMUM_IMAGE_SIZE) {
throw errors.createError(`Invalid final image size: ${action.data.size.final.value}`);
}
if (!_.isBoolean(action.data.size.final.estimation)) {
throw errors.createError(`Invalid final image size estimation flag: ${action.data.size.final.estimation}`);
}
if (action.data.url && !_.isString(action.data.url)) {
throw errors.createError(`Invalid image url: ${action.data.url}`);
}

View File

@ -18,7 +18,6 @@
const _ = require('lodash');
const electron = require('electron');
const imageStream = require('../../../../image-stream');
const errors = require('../../../../shared/errors');
module.exports = function($q, SupportedFormatsModel) {
@ -47,7 +46,7 @@ module.exports = function($q, SupportedFormatsModel) {
* });
*/
this.selectImage = () => {
return $q((resolve, reject) => {
return $q((resolve) => {
electron.remote.dialog.showOpenDialog(currentWindow, {
// This variable is set when running in GNU/Linux from
@ -73,17 +72,8 @@ module.exports = function($q, SupportedFormatsModel) {
// `_.first` is smart enough to not throw and return `undefined`
// if we pass it an `undefined` value (e.g: when the selection
// dialog was cancelled).
const imagePath = _.first(files);
return resolve(_.first(files));
if (!imagePath) {
return resolve();
}
return imageStream.getImageMetadata(imagePath).then((metadata) => {
metadata.path = imagePath;
metadata.size = metadata.size.final.value;
return resolve(metadata);
}).catch(reject);
});
});
};

View File

@ -17,7 +17,6 @@
'use strict';
const _ = require('lodash');
const fs = require('fs');
/**
* @summary Dropzone directive
@ -60,10 +59,7 @@ module.exports = ($timeout) => {
// Pass the filename as a named
// parameter called `$file`
$file: {
path: filename,
size: fs.statSync(filename).size
}
$file: filename
});
});

View File

@ -21,6 +21,7 @@ const Bluebird = require('bluebird');
const path = require('path');
const messages = require('../../../../shared/messages');
const errors = require('../../../../shared/errors');
const imageStream = require('../../../../image-stream');
module.exports = function(
SupportedFormatsModel,
@ -107,6 +108,22 @@ module.exports = function(
}).catch(ErrorService.reportException);
};
/**
* @summary Select an image by path
* @function
* @public
*
* @param {String} imagePath - image path
*
* @example
* ImageSelectionController.selectImageByPath('path/to/image.img');
*/
this.selectImageByPath = (imagePath) => {
imageStream.getImageMetadata(imagePath)
.then(this.selectImage)
.catch(ErrorService.reportException);
};
/**
* @summary Open image selector
* @function
@ -118,16 +135,16 @@ module.exports = function(
this.openImageSelector = () => {
AnalyticsService.logEvent('Open image selector');
OSDialogService.selectImage().then((image) => {
OSDialogService.selectImage().then((imagePath) => {
// Avoid analytics and selection state changes
// if no file was resolved from the dialog.
if (!image) {
if (!imagePath) {
AnalyticsService.logEvent('Image selector closed');
return;
}
this.selectImage(image);
this.selectImageByPath(imagePath);
}).catch(ErrorService.reportException);
};

View File

@ -1,6 +1,6 @@
<div class="page-main row around-xs">
<div class="col-xs" ng-controller="ImageSelectionController as image">
<div class="box text-center relative" os-dropzone="image.selectImage($file)">
<div class="box text-center relative" os-dropzone="image.selectImageByPath($file)">
<svg-icon
class="center-block"

View File

@ -195,6 +195,7 @@ exports.extractImage = (archive, hooks) => {
}).then((results) => {
results.metadata.stream = results.imageStream;
results.metadata.transform = new PassThroughStream();
results.metadata.path = archive;
results.metadata.size = {
original: imageEntry.size,

View File

@ -48,6 +48,7 @@ module.exports = {
*/
'application/x-bzip2': (file, options) => {
return Bluebird.props({
path: file,
stream: fs.createReadStream(file),
size: {
original: options.size,
@ -76,6 +77,7 @@ module.exports = {
'application/gzip': (file, options) => {
return gzip.getUncompressedSize(file).then((uncompressedSize) => {
return Bluebird.props({
path: file,
stream: fs.createReadStream(file),
size: {
original: options.size,
@ -109,6 +111,7 @@ module.exports = {
});
}).then((metadata) => {
return {
path: file,
stream: fs.createReadStream(file),
size: {
original: options.size,
@ -151,6 +154,7 @@ module.exports = {
*/
'application/octet-stream': (file, options) => {
return Bluebird.props({
path: file,
stream: fs.createReadStream(file),
size: {
original: options.size,

View File

@ -142,7 +142,31 @@ exports.isSourceDrive = (drive, image) => {
* }
*/
exports.isDriveLargeEnough = (drive, image) => {
return _.get(drive, [ 'size' ], UNKNOWN_SIZE) >= _.get(image, [ 'size' ], UNKNOWN_SIZE);
const driveSize = _.get(drive, [ 'size' ], UNKNOWN_SIZE);
if (_.get(image, [ 'size', 'final', 'estimation' ])) {
// If the drive size is smaller than the original image size, and
// the final image size is just an estimation, then we stop right
// here, based on the assumption that the final size will never
// be less than the original size.
if (driveSize < _.get(image, [ 'size', 'original' ], UNKNOWN_SIZE)) {
return false;
}
// If the final image size is just an estimation then consider it
// large enough. In the worst case, the user gets an error saying
// the drive has ran out of space, instead of prohibiting the flash
// at all, when the estimation may be wrong.
return true;
}
return driveSize >= _.get(image, [
'size',
'final',
'value'
], UNKNOWN_SIZE);
};
/**

View File

@ -118,7 +118,13 @@ describe('Browser: DrivesModel', function() {
SelectionStateModel.removeDrive();
SelectionStateModel.setImage({
path: this.imagePath,
size: 999999999,
size: {
original: 999999999,
final: {
estimation: false,
value: 999999999
}
},
recommendedDriveSize: 2000000000
});
});

View File

@ -221,7 +221,13 @@ describe('Browser: SelectionState', function() {
beforeEach(function() {
this.image = {
path: 'foo.img',
size: 999999999,
size: {
original: 999999999,
final: {
estimation: false,
value: 999999999
}
},
recommendedDriveSize: 1000000000,
url: 'https://www.raspbian.org',
supportUrl: 'https://www.raspbian.org/forums/',
@ -336,7 +342,13 @@ describe('Browser: SelectionState', function() {
it('should override the image', function() {
SelectionStateModel.setImage({
path: 'bar.img',
size: 999999999
size: {
original: 999999999,
final: {
estimation: false,
value: 999999999
}
}
});
const imagePath = SelectionStateModel.getImagePath();
@ -369,7 +381,13 @@ describe('Browser: SelectionState', function() {
it('should be able to set an image', function() {
SelectionStateModel.setImage({
path: 'foo.img',
size: 999999999
size: {
original: 999999999,
final: {
estimation: false,
value: 999999999
}
}
});
const imagePath = SelectionStateModel.getImagePath();
@ -381,7 +399,13 @@ describe('Browser: SelectionState', function() {
it('should throw if no path', function() {
m.chai.expect(function() {
SelectionStateModel.setImage({
size: 999999999
size: {
original: 999999999,
final: {
estimation: false,
value: 999999999
}
}
});
}).to.throw('Missing image path');
});
@ -390,7 +414,13 @@ describe('Browser: SelectionState', function() {
m.chai.expect(function() {
SelectionStateModel.setImage({
path: 123,
size: 999999999
size: {
original: 999999999,
final: {
estimation: false,
value: 999999999
}
}
});
}).to.throw('Invalid image path: 123');
});
@ -403,40 +433,163 @@ describe('Browser: SelectionState', function() {
}).to.throw('Missing image size');
});
it('should throw if size is not a number', function() {
it('should throw if size is not a plain object', function() {
m.chai.expect(function() {
SelectionStateModel.setImage({
path: 'foo.img',
size: '999999999'
size: 999999999
});
}).to.throw('Invalid image size: 999999999');
});
it('should throw if url is defined but its not a string', function() {
it('should throw if the original size is not a number', function() {
m.chai.expect(function() {
SelectionStateModel.setImage({
path: 'foo.img',
size: 999999999,
size: {
original: '999999999',
final: {
estimation: false,
value: 999999999
}
}
});
}).to.throw('Invalid original image size: 999999999');
});
it('should throw if the original size is a float number', function() {
m.chai.expect(function() {
SelectionStateModel.setImage({
path: 'foo.img',
size: {
original: 999999999.999,
final: {
estimation: false,
value: 999999999
}
}
});
}).to.throw('Invalid original image size: 999999999.999');
});
it('should throw if the original size is negative', function() {
m.chai.expect(function() {
SelectionStateModel.setImage({
path: 'foo.img',
size: {
original: -1,
final: {
estimation: false,
value: 999999999
}
}
});
}).to.throw('Invalid original image size: -1');
});
it('should throw if the final size is not a number', function() {
m.chai.expect(function() {
SelectionStateModel.setImage({
path: 'foo.img',
size: {
original: 999999999,
final: {
estimation: false,
value: '999999999'
}
}
});
}).to.throw('Invalid final image size: 999999999');
});
it('should throw if the final size is a float number', function() {
m.chai.expect(function() {
SelectionStateModel.setImage({
path: 'foo.img',
size: {
original: 999999999,
final: {
estimation: false,
value: 999999999.999
}
}
});
}).to.throw('Invalid final image size: 999999999.999');
});
it('should throw if the final size is negative', function() {
m.chai.expect(function() {
SelectionStateModel.setImage({
path: 'foo.img',
size: {
original: 999999999,
final: {
estimation: false,
value: -1
}
}
});
}).to.throw('Invalid final image size: -1');
});
it('should throw if the final size estimation flag is not a boolean', function() {
m.chai.expect(function() {
SelectionStateModel.setImage({
path: 'foo.img',
size: {
original: 999999999,
final: {
estimation: 'false',
value: 999999999
}
}
});
}).to.throw('Invalid final image size estimation flag: false');
});
it('should throw if url is defined but it\'s not a string', function() {
m.chai.expect(function() {
SelectionStateModel.setImage({
path: 'foo.img',
size: {
original: 999999999,
final: {
estimation: false,
value: 999999999
}
},
url: 1234
});
}).to.throw('Invalid image url: 1234');
});
it('should throw if name is defined but its not a string', function() {
it('should throw if name is defined but it\'s not a string', function() {
m.chai.expect(function() {
SelectionStateModel.setImage({
path: 'foo.img',
size: 999999999,
size: {
original: 999999999,
final: {
estimation: false,
value: 999999999
}
},
name: 1234
});
}).to.throw('Invalid image name: 1234');
});
it('should throw if logo is defined but its not a string', function() {
it('should throw if logo is defined but it\'s not a string', function() {
m.chai.expect(function() {
SelectionStateModel.setImage({
path: 'foo.img',
size: 999999999,
size: {
original: 999999999,
final: {
estimation: false,
value: 999999999
}
},
logo: 1234
});
}).to.throw('Invalid image logo: 1234');
@ -457,7 +610,13 @@ describe('Browser: SelectionState', function() {
SelectionStateModel.setImage({
path: 'foo.img',
size: 9999999999
size: {
original: 9999999999,
final: {
estimation: false,
value: 9999999999
}
}
});
m.chai.expect(SelectionStateModel.hasDrive()).to.be.false;
@ -479,7 +638,13 @@ describe('Browser: SelectionState', function() {
SelectionStateModel.setImage({
path: 'foo.img',
size: 999999999,
size: {
original: 999999999,
final: {
estimation: false,
value: 999999999
}
},
recommendedDriveSize: 1500000000
});
@ -515,7 +680,13 @@ describe('Browser: SelectionState', function() {
SelectionStateModel.setImage({
path: imagePath,
size: 999999999
size: {
original: 999999999,
final: {
estimation: false,
value: 999999999
}
}
});
m.chai.expect(SelectionStateModel.hasDrive()).to.be.false;
@ -542,7 +713,13 @@ describe('Browser: SelectionState', function() {
SelectionStateModel.setImage({
path: 'foo.img',
size: 999999999
size: {
original: 999999999,
final: {
estimation: false,
value: 999999999
}
}
});
});

View File

@ -17,7 +17,6 @@
'use strict';
const m = require('mochainon');
const fs = require('fs');
const angular = require('angular');
require('angular-mocks');
@ -40,20 +39,11 @@ describe('Browser: OSDropzone', function() {
}));
it('should pass the file back to the callback as $file', function(done) {
const statStub = m.sinon.stub(fs, 'statSync');
$rootScope.onDropZone = function(file) {
statStub.restore();
m.chai.expect(file).to.deep.equal({
path: '/foo/bar',
size: 999999999
});
m.chai.expect(file).to.deep.equal('/foo/bar');
done();
};
statStub.returns({
size: 999999999
});
const element = $compile('<div os-dropzone="onDropZone($file)">Drop a file here</div>')($rootScope);
$rootScope.$digest();
@ -73,17 +63,11 @@ describe('Browser: OSDropzone', function() {
});
it('should pass undefined to the callback if not passing $file', function(done) {
const statStub = m.sinon.stub(fs, 'statSync');
$rootScope.onDropZone = function(file) {
statStub.restore();
m.chai.expect(file).to.be.undefined;
done();
};
statStub.returns({
size: 999999999
});
const element = $compile('<div os-dropzone="onDropZone()">Drop a file here</div>')($rootScope);
$rootScope.$digest();

View File

@ -43,7 +43,13 @@ describe('Browser: MainPage', function() {
SelectionStateModel.setImage({
path: 'rpi.img',
size: 99999
size: {
original: 99999,
final: {
estimation: false,
value: 99999
}
}
});
m.chai.expect(controller.shouldDriveStepBeDisabled()).to.be.false;
@ -71,7 +77,13 @@ describe('Browser: MainPage', function() {
SelectionStateModel.clear();
SelectionStateModel.setImage({
path: 'rpi.img',
size: 99999
size: {
original: 99999,
final: {
estimation: false,
value: 99999
}
}
});
m.chai.expect(controller.shouldFlashStepBeDisabled()).to.be.true;
@ -118,7 +130,13 @@ describe('Browser: MainPage', function() {
SelectionStateModel.setImage({
path: 'rpi.img',
size: 99999
size: {
original: 99999,
final: {
estimation: false,
value: 99999
}
}
});
m.chai.expect(controller.shouldFlashStepBeDisabled()).to.be.false;
@ -159,7 +177,13 @@ describe('Browser: MainPage', function() {
SelectionStateModel.setImage({
path: path.join(__dirname, 'foo', 'bar.img'),
size: 999999999
size: {
original: 999999999,
final: {
estimation: false,
value: 999999999
}
}
});
m.chai.expect(controller.getImageBasename()).to.equal('bar.img');

View File

@ -47,6 +47,7 @@ describe('ImageStream: BZ2', function() {
imageStream.getImageMetadata(image).then((metadata) => {
m.chai.expect(metadata).to.deep.equal({
path: image,
size: {
original: expectedSize,
final: {

View File

@ -48,6 +48,7 @@ describe('ImageStream: GZ', function() {
imageStream.getImageMetadata(image).then((metadata) => {
m.chai.expect(metadata).to.deep.equal({
path: image,
size: {
original: compressedSize,
final: {

View File

@ -46,6 +46,7 @@ describe('ImageStream: IMG', function() {
imageStream.getImageMetadata(image).then((metadata) => {
m.chai.expect(metadata).to.deep.equal({
path: image,
size: {
original: expectedSize,
final: {

View File

@ -48,6 +48,7 @@ describe('ImageStream: XZ', function() {
imageStream.getImageMetadata(image).then((metadata) => {
m.chai.expect(metadata).to.deep.equal({
path: image,
size: {
original: compressedSize,
final: {

View File

@ -71,6 +71,7 @@ describe('ImageStream: ZIP', function() {
imageStream.getImageMetadata(image).then((metadata) => {
m.chai.expect(metadata).to.deep.equal({
path: image,
size: {
original: expectedSize,
final: {

View File

@ -303,52 +303,219 @@ describe('Shared: DriveConstraints', function() {
describe('.isDriveLargeEnough()', function() {
it('should return true if the drive size is greater than the image size', function() {
const result = constraints.isDriveLargeEnough({
device: '/dev/disk1',
name: 'USB Drive',
size: 1000000001,
protected: false
}, {
path: 'rpi.img',
size: 1000000000
});
m.chai.expect(result).to.be.true;
});
it('should return true if the drive size is equal to the image size', function() {
const result = constraints.isDriveLargeEnough({
beforeEach(function() {
this.drive = {
device: '/dev/disk1',
name: 'USB Drive',
size: 1000000000,
protected: false
}, {
path: 'rpi.img',
size: 1000000000
});
m.chai.expect(result).to.be.true;
};
});
it('should return false if the drive size is less than the image size', function() {
const result = constraints.isDriveLargeEnough({
device: '/dev/disk1',
name: 'USB Drive',
size: 1000000000,
protected: false
}, {
path: 'rpi.img',
size: 1000000001
describe('given the final image size estimation flag is false', function() {
describe('given the original size is less than the drive size', function() {
beforeEach(function() {
this.image = {
path: path.join(__dirname, 'rpi.img'),
size: {
original: this.drive.size - 1,
final: {
estimation: false
}
}
};
});
it('should return true if the final size is less than the drive size', function() {
this.image.size.final.value = this.drive.size - 1;
m.chai.expect(constraints.isDriveLargeEnough(this.drive, this.image)).to.be.true;
});
it('should return true if the final size is equal to the drive size', function() {
this.image.size.final.value = this.drive.size;
m.chai.expect(constraints.isDriveLargeEnough(this.drive, this.image)).to.be.true;
});
it('should return false if the final size is greater than the drive size', function() {
this.image.size.final.value = this.drive.size + 1;
m.chai.expect(constraints.isDriveLargeEnough(this.drive, this.image)).to.be.false;
});
});
describe('given the original size is equal to the drive size', function() {
beforeEach(function() {
this.image = {
path: path.join(__dirname, 'rpi.img'),
size: {
original: this.drive.size,
final: {
estimation: false
}
}
};
});
it('should return true if the final size is less than the drive size', function() {
this.image.size.final.value = this.drive.size - 1;
m.chai.expect(constraints.isDriveLargeEnough(this.drive, this.image)).to.be.true;
});
it('should return true if the final size is equal to the drive size', function() {
this.image.size.final.value = this.drive.size;
m.chai.expect(constraints.isDriveLargeEnough(this.drive, this.image)).to.be.true;
});
it('should return false if the final size is greater than the drive size', function() {
this.image.size.final.value = this.drive.size + 1;
m.chai.expect(constraints.isDriveLargeEnough(this.drive, this.image)).to.be.false;
});
});
describe('given the original size is greater than the drive size', function() {
beforeEach(function() {
this.image = {
path: path.join(__dirname, 'rpi.img'),
size: {
original: this.drive.size + 1,
final: {
estimation: false
}
}
};
});
it('should return true if the final size is less than the drive size', function() {
this.image.size.final.value = this.drive.size - 1;
m.chai.expect(constraints.isDriveLargeEnough(this.drive, this.image)).to.be.true;
});
it('should return true if the final size is equal to the drive size', function() {
this.image.size.final.value = this.drive.size;
m.chai.expect(constraints.isDriveLargeEnough(this.drive, this.image)).to.be.true;
});
it('should return false if the final size is greater than the drive size', function() {
this.image.size.final.value = this.drive.size + 1;
m.chai.expect(constraints.isDriveLargeEnough(this.drive, this.image)).to.be.false;
});
});
});
describe('given the final image size estimation flag is true', function() {
describe('given the original size is less than the drive size', function() {
beforeEach(function() {
this.image = {
path: path.join(__dirname, 'rpi.img'),
size: {
original: this.drive.size - 1,
final: {
estimation: true
}
}
};
});
it('should return true if the final size is less than the drive size', function() {
this.image.size.final.value = this.drive.size - 1;
m.chai.expect(constraints.isDriveLargeEnough(this.drive, this.image)).to.be.true;
});
it('should return true if the final size is equal to the drive size', function() {
this.image.size.final.value = this.drive.size;
m.chai.expect(constraints.isDriveLargeEnough(this.drive, this.image)).to.be.true;
});
it('should return true if the final size is greater than the drive size', function() {
this.image.size.final.value = this.drive.size + 1;
m.chai.expect(constraints.isDriveLargeEnough(this.drive, this.image)).to.be.true;
});
});
describe('given the original size is equal to the drive size', function() {
beforeEach(function() {
this.image = {
path: path.join(__dirname, 'rpi.img'),
size: {
original: this.drive.size,
final: {
estimation: true
}
}
};
});
it('should return true if the final size is less than the drive size', function() {
this.image.size.final.value = this.drive.size - 1;
m.chai.expect(constraints.isDriveLargeEnough(this.drive, this.image)).to.be.true;
});
it('should return true if the final size is equal to the drive size', function() {
this.image.size.final.value = this.drive.size;
m.chai.expect(constraints.isDriveLargeEnough(this.drive, this.image)).to.be.true;
});
it('should return true if the final size is greater than the drive size', function() {
this.image.size.final.value = this.drive.size + 1;
m.chai.expect(constraints.isDriveLargeEnough(this.drive, this.image)).to.be.true;
});
});
describe('given the original size is greater than the drive size', function() {
beforeEach(function() {
this.image = {
path: path.join(__dirname, 'rpi.img'),
size: {
original: this.drive.size + 1,
final: {
estimation: true
}
}
};
});
it('should return false if the final size is less than the drive size', function() {
this.image.size.final.value = this.drive.size - 1;
m.chai.expect(constraints.isDriveLargeEnough(this.drive, this.image)).to.be.false;
});
it('should return false if the final size is equal to the drive size', function() {
this.image.size.final.value = this.drive.size;
m.chai.expect(constraints.isDriveLargeEnough(this.drive, this.image)).to.be.false;
});
it('should return false if the final size is greater than the drive size', function() {
this.image.size.final.value = this.drive.size + 1;
m.chai.expect(constraints.isDriveLargeEnough(this.drive, this.image)).to.be.false;
});
});
m.chai.expect(result).to.be.false;
});
it('should return false if the drive is undefined', function() {
const result = constraints.isDriveLargeEnough(undefined, {
path: 'rpi.img',
size: 1000000000
path: path.join(__dirname, 'rpi.img'),
size: {
original: 1000000000,
final: {
estimation: false,
value: 1000000000
}
}
});
m.chai.expect(result).to.be.false;
@ -381,7 +548,7 @@ describe('Shared: DriveConstraints', function() {
size: 2000000001,
protected: false
}, {
path: 'rpi.img',
path: path.join(__dirname, 'rpi.img'),
size: 1000000000,
recommendedDriveSize: 2000000000
});
@ -396,7 +563,7 @@ describe('Shared: DriveConstraints', function() {
size: 2000000000,
protected: false
}, {
path: 'rpi.img',
path: path.join(__dirname, 'rpi.img'),
size: 1000000000,
recommendedDriveSize: 2000000000
});
@ -411,7 +578,7 @@ describe('Shared: DriveConstraints', function() {
size: 2000000000,
protected: false
}, {
path: 'rpi.img',
path: path.join(__dirname, 'rpi.img'),
size: 1000000000,
recommendedDriveSize: 2000000001
});
@ -426,7 +593,7 @@ describe('Shared: DriveConstraints', function() {
size: 2000000000,
protected: false
}, {
path: 'rpi.img',
path: path.join(__dirname, 'rpi.img'),
size: 1000000000
});
@ -435,7 +602,7 @@ describe('Shared: DriveConstraints', function() {
it('should return false if the drive is undefined', function() {
const result = constraints.isDriveSizeRecommended(undefined, {
path: 'rpi.img',
path: path.join(__dirname, 'rpi.img'),
size: 1000000000,
recommendedDriveSize: 1000000000
});
@ -491,28 +658,52 @@ describe('Shared: DriveConstraints', function() {
it('should return false if the drive is not large enough and is a source drive', function() {
m.chai.expect(constraints.isDriveValid(this.drive, {
path: path.join(this.mountpoint, 'rpi.img'),
size: 5000000000
size: {
original: 5000000000,
final: {
estimation: false,
value: 5000000000
}
}
})).to.be.false;
});
it('should return false if the drive is not large enough and is not a source drive', function() {
m.chai.expect(constraints.isDriveValid(this.drive, {
path: path.resolve(this.mountpoint, '../bar/rpi.img'),
size: 5000000000
size: {
original: 5000000000,
final: {
estimation: false,
value: 5000000000
}
}
})).to.be.false;
});
it('should return false if the drive is large enough and is a source drive', function() {
m.chai.expect(constraints.isDriveValid(this.drive, {
path: path.join(this.mountpoint, 'rpi.img'),
size: 2000000000
size: {
original: 2000000000,
final: {
estimation: false,
value: 2000000000
}
}
})).to.be.false;
});
it('should return false if the drive is large enough and is not a source drive', function() {
m.chai.expect(constraints.isDriveValid(this.drive, {
path: path.resolve(this.mountpoint, '../bar/rpi.img'),
size: 2000000000
size: {
original: 2000000000,
final: {
estimation: false,
value: 2000000000
}
}
})).to.be.false;
});
@ -527,28 +718,52 @@ describe('Shared: DriveConstraints', function() {
it('should return false if the drive is not large enough and is a source drive', function() {
m.chai.expect(constraints.isDriveValid(this.drive, {
path: path.join(this.mountpoint, 'rpi.img'),
size: 5000000000
size: {
original: 5000000000,
final: {
estimation: false,
value: 5000000000
}
}
})).to.be.false;
});
it('should return false if the drive is not large enough and is not a source drive', function() {
m.chai.expect(constraints.isDriveValid(this.drive, {
path: path.resolve(this.mountpoint, '../bar/rpi.img'),
size: 5000000000
size: {
original: 5000000000,
final: {
estimation: false,
value: 5000000000
}
}
})).to.be.false;
});
it('should return false if the drive is large enough and is a source drive', function() {
m.chai.expect(constraints.isDriveValid(this.drive, {
path: path.join(this.mountpoint, 'rpi.img'),
size: 2000000000
size: {
original: 2000000000,
final: {
estimation: false,
value: 2000000000
}
}
})).to.be.false;
});
it('should return true if the drive is large enough and is not a source drive', function() {
m.chai.expect(constraints.isDriveValid(this.drive, {
path: path.resolve(this.mountpoint, '../bar/rpi.img'),
size: 2000000000
size: {
original: 2000000000,
final: {
estimation: false,
value: 2000000000
}
}
})).to.be.true;
});