diff --git a/src/RokuDeploy.spec.ts b/src/RokuDeploy.spec.ts index d93702f..0e0daea 100644 --- a/src/RokuDeploy.spec.ts +++ b/src/RokuDeploy.spec.ts @@ -1195,8 +1195,77 @@ describe('index', () => { } assert.fail('Should not have succeeded'); }); + + it('should throw with HPE_INVALID_CONSTANT and then succeed on retry', async () => { + let doPostStub = sinon.stub(rokuDeploy as any, 'doPostRequest'); + doPostStub.onFirstCall().throws((params) => { + throw new ErrorWithCode(); + }); + doPostStub.onSecondCall().returns({ body: '..."fileType":"squashfs"...' }); + try { + await rokuDeploy.convertToSquashfs(options); + } catch (e) { + assert.fail('Should not have throw'); + } + }); + + it('should throw and not retry', async () => { + let doPostStub = sinon.stub(rokuDeploy as any, 'doPostRequest'); + doPostStub.onFirstCall().throws((params) => { + throw new ErrorWithCode('Something else'); + }); + try { + await rokuDeploy.convertToSquashfs(options); + } catch (e) { + expect(e).to.be.instanceof(ErrorWithCode); + expect(e['code']).to.be.eql('Something else'); + return; + } + assert.fail('Should not have throw'); + }); + + it('should throw with HPE_INVALID_CONSTANT and then fail on retry', async () => { + let doPostStub = sinon.stub(rokuDeploy as any, 'doPostRequest'); + doPostStub.onFirstCall().throws((params) => { + throw new ErrorWithCode(); + }); + doPostStub.onSecondCall().returns({ body: '..."fileType":"zip"...' }); + try { + await rokuDeploy.convertToSquashfs(options); + } catch (e) { + expect(e).to.be.instanceof(errors.ConvertError); + return; + } + assert.fail('Should not have throw'); + }); + + it('should fail with HPE_INVALID_CONSTANT and then throw on retry', async () => { + let doPostStub = sinon.stub(rokuDeploy as any, 'doPostRequest'); + doPostStub.onFirstCall().throws((params) => { + throw new ErrorWithCode(); + }); + doPostStub.onSecondCall().throws((params) => { + throw new Error('Never seen'); + }); + try { + await rokuDeploy.convertToSquashfs(options); + } catch (e) { + expect(e).to.be.instanceof(ErrorWithCode); + return; + } + assert.fail('Should not have throw'); + }); }); + class ErrorWithCode extends Error { + code; + + constructor(code = 'HPE_INVALID_CONSTANT') { + super(); + this.code = code; + } + } + describe('rekeyDevice', () => { beforeEach(() => { const body = ` diff --git a/src/RokuDeploy.ts b/src/RokuDeploy.ts index 3a04b2e..5468799 100644 --- a/src/RokuDeploy.ts +++ b/src/RokuDeploy.ts @@ -507,8 +507,27 @@ export class RokuDeploy { archive: '', mysubmit: 'Convert to squashfs' }); - - let results = await this.doPostRequest(requestOptions); + let results; + try { + results = await this.doPostRequest(requestOptions); + } catch (error) { + //Occasionally this error is seen if the zip size and file name length at the + //wrong combination. The device fails to respond to our request with a valid response. + //The device successfully converted the zip, so ping the device and and check the response + //for "fileType": "squashfs" then return a happy response, otherwise throw the original error + if ((error as any).code === 'HPE_INVALID_CONSTANT') { + try { + results = await this.doPostRequest(requestOptions, false); + if (/"fileType"\s*:\s*"squashfs"/.test(results.body)) { + return results; + } + } catch (e) { + throw error; + } + } else { + throw error; + } + } if (results.body.indexOf('Conversion succeeded') === -1) { throw new errors.ConvertError('Squashfs conversion failed'); }