| var BUFFER_SIZE = 8192; |
| |
| QUnit.test("createSocket_", function(assert) { |
| var client = new FTPClient(MockSocket); |
| var createSocket_ = client.test.createSocket_, FTPInfo = client.test.FTPInfo; |
| QUnit.stop(); |
| createSocket_().then(function(socketInfo){ |
| QUnit.ok(socketInfo.socketId >= 0, "socket created"); |
| }).catch(function (error) { |
| QUnit.equal(error, "This should have succeeded"); |
| }); |
| QUnit.start(); |
| }); |
| |
| QUnit.test("connectWrapper_", function() { |
| QUnit.stop(); |
| var client = new FTPClient(MockSocket), |
| createSocket_ = client.test.createSocket_, |
| connectWrapper_ = client.test.connectWrapper_; |
| expect(5); |
| createSocket_().then(function (socketInfo) { |
| return connectWrapper_(socketInfo.socketId, "cmu.edu", 22); |
| }).then(function (result) { |
| QUnit.ok(result >= 0, "connection successful"); |
| }).catch(function (error) { |
| QUnit.equal(error, "This should have suceeded"); |
| }); |
| createSocket_().then(function (socketInfo) { |
| return connectWrapper_(socketInfo.socketId, "", 22); |
| }).then(function (result) { |
| QUnit.equal(result, "connection should not succeed"); |
| }).catch(function (error) { |
| QUnit.ok(error instanceof Error === true, "error received"); |
| QUnit.equal(error.message, "Error code -9", |
| "connection fail expected"); |
| }); |
| createSocket_().then(function (socketInfo) { |
| return connectWrapper_(socketInfo.socketId, "cmu.edu", NaN); |
| }).then(function (result) { |
| QUnit.equal(result, "connection should not succeed"); |
| }).catch(function (error) { |
| QUnit.ok(error instanceof Error === true, "error received"); |
| QUnit.equal(error.message, "Error code -9", |
| "connection fail expected"); |
| }); |
| QUnit.start(); |
| }); |
| |
| QUnit.test("connect", function() { |
| expect(5); |
| QUnit.stop(); |
| var client = new FTPClient(MockSocket); |
| client.connect("google.com", 22).then(function (reply) { |
| QUnit.equal(reply, "220 Service ready for new user\r\n", |
| "connection successful"); |
| }).catch(function(error){ |
| QUnit.equal(error, "This should have suceeded"); |
| }); |
| client = new FTPClient(MockSocket); |
| client.connect("", 22).then(function (reply) { |
| QUnit.equal(reply, "Connection should not succeed"); |
| }).catch(function (error){ |
| QUnit.ok(error instanceof Error === true, "error received"); |
| QUnit.equal(error.message, "Error code -9", |
| "Connection fail expected"); |
| }); |
| client = new FTPClient(MockSocket); |
| client.connect("cmu.edu","portNaN").then(function (reply) { |
| QUnit.equal(reply, "Connection should not succeed"); |
| }).catch(function (error) { |
| QUnit.ok(error instanceof Error === true, "error received"); |
| QUnit.equal(error.message, "Error code -9", |
| "Connection fail expected"); |
| QUnit.start(); |
| }); |
| }); |
| |
| QUnit.test("splitLines_", function() { |
| expect(27); |
| // case I |
| var client = new FTPClient(MockSocket); |
| var FTPInfo = client.test.FTPInfo, splitLines_ = client.test.splitLines_, |
| commandRawData = FTPInfo.commandRawData, encoder = new TextEncoder("utf-8"); |
| |
| var receivedData = encoder.encode("rnr\nA\r\n"); |
| splitLines_(receivedData); |
| QUnit.deepEqual(commandRawData.buffer, new Uint8Array(BUFFER_SIZE), "no leftOver"); |
| QUnit.equal(commandRawData.buffOffset, 0, "buffOffset 0 - no leftOver"); |
| QUnit.deepEqual(commandRawData.parsedLines, ["rnr\n", "A\r\n"], "parsedLines"); |
| |
| // case II |
| receivedData = encoder.encode("google "); |
| splitLines_(receivedData); |
| QUnit.deepEqual(commandRawData.buffer.subarray(0, receivedData.byteLength), |
| receivedData, "leftOvers"); |
| QUnit.equal(commandRawData.buffOffset, receivedData.byteLength); |
| |
| // case III |
| receivedData = encoder.encode("love\r\n"); |
| splitLines_(receivedData); |
| QUnit.deepEqual(commandRawData.parsedLines, ["rnr\n", "A\r\n", "google love\r\n"], |
| "added new parsed line"); |
| QUnit.deepEqual(commandRawData.buffer, new Uint8Array(BUFFER_SIZE), |
| "reset buffer after combining"); |
| QUnit.equal(commandRawData.buffOffset, 0, "reset buffOffset after combining"); |
| |
| // case Iv |
| receivedData = new Uint8Array([230, 176]); |
| splitLines_(receivedData); |
| QUnit.deepEqual(commandRawData.buffer.subarray(0, receivedData.byteLength), |
| receivedData, "wild character split"); |
| QUnit.equal(commandRawData.buffOffset, receivedData.byteLength); |
| |
| // case V |
| receivedData = new Uint8Array([180, 32, 119, 105, 108, 100, 13, 10, 116]); |
| splitLines_(receivedData); |
| QUnit.deepEqual(commandRawData.buffer.subarray(0,1), new Uint8Array([116])); |
| QUnit.deepEqual(commandRawData.parsedLines, ["rnr\n", "A\r\n", "google love\r\n", |
| "水 wild\r\n"]); |
| QUnit.equal(commandRawData.buffOffset, 1, "combined data, rest buffOffset"); |
| |
| //case VI |
| receivedData = new Uint8Array([111, 98, 101]); |
| splitLines_(receivedData); |
| QUnit.deepEqual(commandRawData.buffer.subarray(0, commandRawData.buffOffset), |
| new Uint8Array([116, 111, 98, 101]), "combined non line data"); |
| client = new FTPClient(MockSocket); |
| FTPInfo = client.test.FTPInfo; |
| splitLines_ = client.test.splitLines_; |
| commandRawData = FTPInfo.commandRawData; |
| receivedData = encoder.encode("320 google\r\n"); |
| splitLines_(receivedData); |
| QUnit.deepEqual(commandRawData.parsedLines, ["320 google\r\n"], "basic test"); |
| QUnit.deepEqual(commandRawData.buffer, new Uint8Array(BUFFER_SIZE), "no left over"); |
| QUnit.equal(commandRawData.buffOffset, 0, "buffOffset remained 0"); |
| |
| var receivedDataI = encoder.encode("320"); |
| splitLines_(receivedDataI); |
| QUnit.deepEqual(commandRawData.parsedLines, ["320 google\r\n"], "uncomsumed line"); |
| QUnit.deepEqual(commandRawData.buffer.subarray(0, commandRawData.buffOffset), receivedDataI, |
| "data stored"); |
| QUnit.equal(commandRawData.buffOffset, receivedDataI.byteLength, |
| "buffOffset reflects dataReceived"); |
| |
| var receivedDataII = encoder.encode(" goog"); |
| splitLines_(receivedDataII); |
| QUnit.deepEqual(commandRawData.parsedLines, ["320 google\r\n"], "unconsumed line"); |
| QUnit.deepEqual(commandRawData.buffer.subarray(0, receivedDataI.byteLength), receivedDataI, |
| "receivedDataI stored"); |
| QUnit.deepEqual(commandRawData.buffer.subarray(receivedDataI.byteLength, commandRawData.buffOffset), |
| receivedDataII, "receivedDataII stored"); |
| QUnit.equal(commandRawData.buffOffset, receivedDataI.byteLength + receivedDataII.byteLength, |
| "buffOffset reflects dataReceived"); |
| |
| var receivedDataIII = encoder.encode("le\r\n"); |
| splitLines_(receivedDataIII); |
| QUnit.deepEqual(commandRawData.parsedLines, ["320 google\r\n", "320 google\r\n"], |
| "unconsumed lines"); |
| QUnit.deepEqual(commandRawData.buffer, new Uint8Array(BUFFER_SIZE), |
| "got full line, buffer now empty"); |
| QUnit.equal(commandRawData.buffOffset, 0, "buffOffset reset"); |
| }); |
| |
| QUnit.test("getReply_ multilined", function() { |
| expect(22); |
| var client = new FTPClient(MockSocket); |
| var FTPInfo = client.test.FTPInfo, getReply_ = client.test.getReply_, |
| commandRawData = FTPInfo.commandRawData, encoder = new TextEncoder("utf-8"); |
| var receivedData = encoder.encode("320-google\r\n"); |
| var responses = getReply_(receivedData); |
| QUnit.deepEqual(commandRawData.parsedLines, ["320-google\r\n"], "basic test"); |
| QUnit.deepEqual(commandRawData.buffer, new Uint8Array(BUFFER_SIZE), "no leftOver"); |
| QUnit.equal(commandRawData.buffOffset, 0, "buffOffset = 0"); |
| QUnit.ok(responses === null, "No response received yet"); |
| |
| var receivedDataI = encoder.encode("love "); |
| responses = getReply_(receivedDataI); |
| QUnit.deepEqual(commandRawData.parsedLines, ["320-google\r\n"], "no new line received"); |
| QUnit.deepEqual(commandRawData.buffer.subarray(0, commandRawData.buffOffset), receivedDataI, |
| "accumulating data"); |
| QUnit.equal(commandRawData.buffOffset, receivedDataI.byteLength, |
| "updated buffOffset"); |
| QUnit.ok(responses === null, "No response received yet"); |
| |
| var receivedDataII = encoder.encode("live "); |
| responses = getReply_(receivedDataII); |
| QUnit.deepEqual(commandRawData.parsedLines, ["320-google\r\n"], "again no new line"); |
| QUnit.deepEqual(commandRawData.buffer.subarray(0, receivedDataI.byteLength), |
| receivedDataI, "previous data is still in the buff"); |
| QUnit.deepEqual(commandRawData.buffer.subarray(receivedDataI.byteLength, |
| receivedDataI.byteLength + receivedDataII.byteLength), receivedDataII, |
| "accumulated new data"); |
| QUnit.equal(commandRawData.buffOffset, receivedDataI.byteLength+receivedDataII.byteLength, |
| "updated buffOffset"); |
| QUnit.ok(responses === null, "No response received yet"); |
| |
| var receivedDataIII = encoder.encode("laugh\r\n"); |
| responses = getReply_(receivedDataIII); |
| QUnit.deepEqual(commandRawData.parsedLines, ["320-google\r\n", "love live laugh\r\n"], |
| "combined replies"); |
| QUnit.deepEqual(commandRawData.buffer, new Uint8Array(BUFFER_SIZE), "reset buffer"); |
| QUnit.equal(commandRawData.buffOffset, 0, "reset buffOffset"); |
| QUnit.ok(responses === null, "No response received yet"); |
| |
| var receivedDataIV = encoder.encode("320"); |
| responses = getReply_(receivedDataIV); |
| QUnit.ok(responses === null, "No response just yet"); |
| var receivedDataV = encoder.encode(" \r\n"); |
| responses = getReply_(receivedDataV); |
| QUnit.deepEqual(responses, ["320-google\r\nlove live laugh\r\n320 \r\n"], |
| "full response received"); |
| QUnit.deepEqual(commandRawData.buffer, new Uint8Array(BUFFER_SIZE), |
| "buffer cleared"); |
| QUnit.equal(commandRawData.buffOffset, 0, "bufferOffsert reset"); |
| QUnit.deepEqual(commandRawData.parsedLines, [], "parsed lines cleared"); |
| }); |
| |
| QUnit.test("getReply_ singlelined", function() { |
| expect(8); |
| var client = new FTPClient(MockSocket); |
| var FTPInfo = client.test.FTPInfo, getReply_ = client.test.getReply_, |
| commandRawData = FTPInfo.commandRawData, encoder = new TextEncoder("utf-8"); |
| var receivedData = encoder.encode("320 google"); |
| var responses = getReply_(receivedData); |
| QUnit.deepEqual(commandRawData.parsedLines, [], "basic test"); |
| QUnit.deepEqual(commandRawData.buffer.subarray(0, receivedData.byteLength), receivedData, |
| "no new lines"); |
| QUnit.equal(commandRawData.buffOffset, receivedData.byteLength, "buffOffset updated"); |
| QUnit.ok(responses === null, "No response received yet"); |
| |
| var receivedDataI = encoder.encode("\r\n"); |
| responses = getReply_(receivedDataI); |
| QUnit.deepEqual(commandRawData.parsedLines, [], "response returned"); |
| QUnit.deepEqual(commandRawData.buffer, new Uint8Array(BUFFER_SIZE)); |
| QUnit.deepEqual(responses, ["320 google\r\n"]); |
| QUnit.equal(commandRawData.buffOffset, 0); |
| }); |
| |
| QUnit.test("getReply_ singlelined & multilined", function() { |
| expect(17); |
| var client = new FTPClient(MockSocket); |
| var FTPInfo = client.test.FTPInfo, getReply_ = client.test.getReply_, |
| commandRawData = FTPInfo.commandRawData, encoder = new TextEncoder("utf-8"); |
| var receivedData = encoder.encode("320 google"); |
| var responses = getReply_(receivedData); |
| QUnit.ok(responses === null, "No response received yet"); |
| var receivedDataI = encoder.encode("\r\n320-google"); |
| responses = getReply_(receivedDataI); |
| var leftOver = encoder.encode("320-google"); |
| QUnit.deepEqual(responses, ["320 google\r\n"], |
| "The singlelined response received"); |
| QUnit.deepEqual(commandRawData.parsedLines, [], "no parsed lines"); |
| QUnit.deepEqual(commandRawData.buffer.subarray(0, leftOver.byteLength), leftOver, |
| "leftOver was stored in buff"); |
| QUnit.equal(commandRawData.buffOffset, leftOver.byteLength, "buffOffset updated"); |
| |
| var receivedDataII = encoder.encode("\r\nnext"); |
| responses = getReply_(receivedDataII); |
| QUnit.ok(responses === null, "No new response received"); |
| QUnit.deepEqual(commandRawData.parsedLines, ["320-google\r\n"], |
| "first line of multiline response"); |
| leftOver = encoder.encode("next"); |
| QUnit.deepEqual(commandRawData.buffer.subarray(0, leftOver.byteLength), leftOver, |
| "leftOver was stored in buff"); |
| QUnit.equal(commandRawData.buffOffset, leftOver.byteLength, "buffOffset updated"); |
| |
| var receivedDataIII = encoder.encode("\r\n320 \r\n"); |
| responses = getReply_(receivedDataIII); |
| QUnit.deepEqual(commandRawData.parsedLines, [], "received full multi-lined response"); |
| QUnit.deepEqual(responses, ["320-google\r\nnext\r\n320 \r\n"], "response"); |
| QUnit.deepEqual(commandRawData.buffer, new Uint8Array(BUFFER_SIZE), "buffer cleared"); |
| QUnit.equal(commandRawData.buffOffset, 0, "buffOffset reset"); |
| |
| var receivedDataIV = encoder.encode("320-multi\r\n320 \r\n320 singlelined\r\n"); |
| responses = getReply_(receivedDataIV); |
| QUnit.deepEqual(commandRawData.parsedLines, [], "recieved response, no parsed lines"); |
| QUnit.deepEqual(responses, ["320-multi\r\n320 \r\n", "320 singlelined\r\n"], |
| "multiple responses received"); |
| QUnit.deepEqual(commandRawData.buffer, new Uint8Array(BUFFER_SIZE), "buffer cleared"); |
| QUnit.equal(commandRawData.buffOffset, 0 , "buffOffset reset"); |
| }); |
| |
| QUnit.test("isLegalCode_", function () { |
| var client = new FTPClient(MockSocket); |
| var isLegalCode_ = client.test.isLegalCode_; |
| QUnit.equal(isLegalCode_(""), false); |
| QUnit.equal(isLegalCode_("01"), false); |
| QUnit.equal(isLegalCode_("1w3"), false); |
| QUnit.equal(isLegalCode_("abc"), false); |
| QUnit.equal(isLegalCode_("012"), false); |
| QUnit.equal(isLegalCode_("123"), true); |
| QUnit.equal(isLegalCode_("hellothere"), false); |
| QUnit.equal(isLegalCode_("000"), false); |
| }); |
| |
| QUnit.test("getReplyCode_", function () { |
| var client = new FTPClient(MockSocket); |
| var getReplyCode_ = client.test.getReplyCode_; |
| QUnit.equal(getReplyCode_(""), undefined); |
| QUnit.equal(getReplyCode_("12\r\n"), undefined); |
| QUnit.equal(getReplyCode_("230-google\r\n"), 230); |
| QUnit.equal(getReplyCode_("09"), undefined); |
| QUnit.equal(getReplyCode_("099"), undefined); |
| QUnit.equal(getReplyCode_("99"), undefined); |
| QUnit.equal(getReplyCode_(" 8"), undefined); |
| QUnit.equal(getReplyCode_(" no digits here\r\n"), undefined); |
| QUnit.equal(getReplyCode_("999 \r\n"), 999); |
| QUnit.equal(getReplyCode_("10000 it's not a reply code"), undefined); |
| }); |
| |
| QUnit.test("onReceiveCallback_", function () { |
| expect(17); |
| var client = new FTPClient(MockSocket); |
| var FTPInfo = client.test.FTPInfo, |
| onReceiveCallback_ = client.test.onReceiveCallback_, |
| commandRawData = FTPInfo.commandRawData, encoder = new TextEncoder("utf-8"); |
| QUnit.stop(); |
| client.connect("cmu.edu", 22).then(function () { |
| QUnit.deepEqual(commandRawData.parsedLines, [], "reply consumed"); |
| QUnit.deepEqual(FTPInfo.serverResponses, [], "reply consumed"); |
| |
| var commandId = FTPInfo.commandId; |
| var sendData = encoder.encode("220 OK\r\n220-multi").buffer; |
| var sendInfo = {socketId: commandId, data: sendData}; |
| |
| onReceiveCallback_(sendInfo); |
| |
| var leftOver = encoder.encode("220-multi"); |
| QUnit.deepEqual(FTPInfo.serverResponses, ["220 OK\r\n"], |
| "recorded server response"); |
| QUnit.deepEqual(commandRawData.parsedLines, [], |
| "returned reply, parsedLines empty"); |
| QUnit.deepEqual(commandRawData.buffer.subarray(0, leftOver.byteLength), |
| leftOver, "leftOver stored in buffer"); |
| QUnit.deepEqual(commandRawData.buffOffset, leftOver.byteLength); |
| |
| sendInfo.data = encoder.encode("line\r\n").buffer; |
| onReceiveCallback_(sendInfo); |
| QUnit.deepEqual(FTPInfo.serverResponses, ["220 OK\r\n"], |
| "complete response has not been received yet"); |
| QUnit.deepEqual(commandRawData.parsedLines, ["220-multiline\r\n"], |
| "begining of multiline"); |
| QUnit.deepEqual(commandRawData.buffer, new Uint8Array(BUFFER_SIZE), |
| "new line recieved, buffer cleared"); |
| QUnit.equal(commandRawData.buffOffset, 0, "buffOffset reset"); |
| |
| sendInfo.data = encoder.encode("220 end\r\n").buffer; |
| onReceiveCallback_(sendInfo); |
| QUnit.deepEqual(FTPInfo.serverResponses, |
| ["220 OK\r\n", "220-multiline\r\n220 end\r\n"], |
| "new response received"); |
| QUnit.deepEqual(commandRawData.parsedLines, [], |
| "full responses received, no parsed lines"); |
| QUnit.deepEqual(commandRawData.buffer, new Uint8Array(BUFFER_SIZE), |
| "new line recieved, buffer cleared"); |
| QUnit.equal(commandRawData.buffOffset, 0, "buffOffset reset"); |
| |
| var responsePromise = client.test.readReply_(); |
| var responsePromiseI = client.test.readReply_(); |
| responsePromise.then(function (reply) { |
| QUnit.equal(reply, "220 OK\r\n", "read single-lined response"); |
| }); |
| responsePromiseI.then(function (reply) { |
| QUnit.equal(reply, "220-multiline\r\n220 end\r\n", |
| "read multilined response"); |
| }); |
| QUnit.deepEqual(FTPInfo.serverResponses, [], "serverResponses cleared"); |
| QUnit.start(); |
| }).catch(function (error) { |
| console.log("INSIDE TEST ERROR:", error); |
| QUnit.equal(error, "This test should have succeeded"); |
| QUnit.start(); |
| }); |
| }); |
| |
| QUnit.test("onReceiveCallback_ preliminary Responses basic", function () { |
| expect(10); |
| var client = new FTPClient(MockSocket); |
| var FTPInfo = client.test.FTPInfo, |
| onReceiveCallback_ = client.test.onReceiveCallback_, |
| readReply_ = client.test.readReply_, |
| readFinalReply_ = client.test.readFinalReply_, |
| commandRawData = FTPInfo.commandRawData, encoder = new TextEncoder("utf-8"); |
| QUnit.stop(); |
| client.connect("cmu.edu", 22).then(function () { |
| QUnit.deepEqual(commandRawData.parsedLines, [], "reply consumed"); |
| QUnit.deepEqual(FTPInfo.serverResponses, [], "reply consumed"); |
| |
| var commandId = FTPInfo.commandId; |
| var sendData = encoder.encode("150 Sending data\r\n").buffer; |
| var sendInfo = {socketId: commandId, data: sendData}; |
| |
| onReceiveCallback_(sendInfo); |
| sendInfo.data = encoder.encode("226 Closing data connection\r\n"); |
| onReceiveCallback_(sendInfo); |
| QUnit.deepEqual(FTPInfo.serverResponses, ["150 Sending data\r\n", |
| "226 Closing data connection\r\n"], |
| "got 1yz server response"); |
| QUnit.deepEqual(commandRawData.parsedLines, [], |
| "returned reply, parsedLines empty"); |
| var response = readReply_("LIST"); |
| response.then(function () { |
| QUnit.equal(FTPInfo.preliminaryState, true, "in preliminary state"); |
| return readFinalReply_(); |
| }).then(function (reply) { |
| QUnit.equal(reply, "226 Closing data connection\r\n", "read final response"); |
| QUnit.equal(FTPInfo.preliminaryState, false); |
| QUnit.deepEqual(FTPInfo.preliminaryRead, null); |
| QUnit.deepEqual(FTPInfo.serverResponses, [], "consumed server responses"); |
| QUnit.deepEqual(commandRawData.parsedLines, [], "no parsed lines"); |
| QUnit.start(); |
| }); |
| }); |
| }); |
| |
| QUnit.test("onReceiveCallback_ preliminary responses", function () { |
| expect(9); |
| var client = new FTPClient(MockSocket); |
| var FTPInfo = client.test.FTPInfo, |
| onReceiveCallback_ = client.test.onReceiveCallback_, |
| readReply_ = client.test.readReply_, |
| readFinalReply_ = client.test.readFinalReply_, |
| commandRawData = FTPInfo.commandRawData, encoder = new TextEncoder("utf-8"); |
| QUnit.stop(); |
| client.connect("cmu.edu", 22).then(function () { |
| QUnit.deepEqual(commandRawData.parsedLines, [], "reply consumed"); |
| QUnit.deepEqual(FTPInfo.serverResponses, [], "reply consumed"); |
| |
| var commandId = FTPInfo.commandId; |
| var sendData = encoder.encode("150 Sending data\r\n").buffer; |
| var sendInfo = {socketId: commandId, data: sendData}; |
| |
| onReceiveCallback_(sendInfo); |
| var responseI = readReply_(); |
| var responseII = readReply_(); |
| |
| sendInfo.data = encoder.encode("226 Closing data connection\r\n"); |
| onReceiveCallback_(sendInfo); |
| |
| sendInfo.data = encoder.encode("220 OK\r\n"); |
| onReceiveCallback_(sendInfo); |
| |
| responseI.then(function (reply) { |
| QUnit.equal(reply, "150 Sending data\r\n"); |
| QUnit.equal(FTPInfo.preliminaryState, true, "entered preliminary state"); |
| QUnit.equal(FTPInfo.pendingReads.length, 1, "one pending read"); |
| return readFinalReply_(); |
| }).then(function (reply) { |
| QUnit.equal(reply, "226 Closing data connection\r\n"); |
| QUnit.deepEqual(FTPInfo.pendingReads, [], "all reads resolved"); |
| QUnit.deepEqual(FTPInfo.serverResponses, [], "consumed all responses"); |
| responseII.then(function (reply) { |
| QUnit.equal(reply, "220 OK\r\n"); |
| QUnit.start(); |
| }).catch(function (error) { |
| throw error; |
| }); |
| }).catch(function (error) { |
| QUnit.equal(error, "This function should have suceeded!"); |
| QUnit.start(); |
| }); |
| }); |
| }); |
| |
| QUnit.test("onReceiveCallback_ preliminary responses", function () { |
| //expect(9); |
| var client = new FTPClient(MockSocket); |
| var FTPInfo = client.test.FTPInfo, |
| onReceiveCallback_ = client.test.onReceiveCallback_, |
| readReply_ = client.test.readReply_, |
| readFinalReply_ = client.test.readFinalReply_, |
| commandRawData = FTPInfo.commandRawData, encoder = new TextEncoder("utf-8"); |
| QUnit.stop(); |
| client.connect("cmu.edu", 22).then(function () { |
| QUnit.deepEqual(commandRawData.parsedLines, [], "reply consumed"); |
| QUnit.deepEqual(FTPInfo.serverResponses, [], "reply consumed"); |
| |
| var commandId = FTPInfo.commandId; |
| var sendData = encoder.encode("220 OK\r\n220 OK\r\n150 Sending data\r\n").buffer; |
| var sendInfo = {socketId: commandId, data: sendData}; |
| |
| readReply_(); |
| readReply_(); |
| QUnit.deepEqual(FTPInfo.pendingReads.length, 2, "two pending reads"); |
| QUnit.deepEqual(FTPInfo.serverResponses, [], "no responses received yet"); |
| |
| onReceiveCallback_(sendInfo); |
| QUnit.deepEqual(FTPInfo.pendingReads.length, 0, "pending reads resolved"); |
| QUnit.deepEqual(FTPInfo.serverResponses, ["150 Sending data\r\n"]); |
| |
| sendInfo.data = encoder.encode("226 Closing data connection\r\n220 OK\r\n"); |
| onReceiveCallback_(sendInfo); |
| QUnit.deepEqual(FTPInfo.preliminaryState, false, |
| "haven't entered preliminary state yet"); |
| QUnit.deepEqual(FTPInfo.serverResponses, ["150 Sending data\r\n", |
| "226 Closing data connection\r\n", "220 OK\r\n"]); |
| readReply_(); |
| QUnit.equal(FTPInfo.preliminaryState, true, |
| "preliminary state encountered"); |
| readReply_(); |
| QUnit.equal(FTPInfo.pendingReads.length, 1, |
| "pending reads but preliminary state"); |
| QUnit.deepEqual(FTPInfo.serverResponses, ["226 Closing data connection\r\n", |
| "220 OK\r\n"]); |
| readFinalReply_(); |
| QUnit.deepEqual(FTPInfo.serverResponses, [], "all responses consumed"); |
| QUnit.deepEqual(FTPInfo.preliminaryState, false, "preliminary state finished"); |
| QUnit.equal(FTPInfo.preliminaryRead, null, "final read returned"); |
| QUnit.start(); |
| }).catch(function (error) { |
| QUnit.equal(error, "This function should have suceeded!"); |
| QUnit.start(); |
| }); |
| }); |
| |
| QUnit.test("onReceiveCallback_ multiple preliminary responses error", function () { |
| expect(6); |
| var client = new FTPClient(MockSocket); |
| var FTPInfo = client.test.FTPInfo, |
| onReceiveCallback_ = client.test.onReceiveCallback_, |
| readReply_ = client.test.readReply_, |
| readFinalReply_ = client.test.readFinalReply_, |
| commandRawData = FTPInfo.commandRawData, encoder = new TextEncoder("utf-8"); |
| QUnit.stop(); |
| client.connect("cmu.edu", 22).then(function () { |
| QUnit.deepEqual(commandRawData.parsedLines, [], "reply consumed"); |
| QUnit.deepEqual(FTPInfo.serverResponses, [], "reply consumed"); |
| |
| var commandId = FTPInfo.commandId; |
| var sendData = encoder.encode("150 Sending data\r\n150 Sending data\r\n").buffer; |
| var sendInfo = {socketId: commandId, data: sendData}; |
| |
| onReceiveCallback_(sendInfo); |
| readReply_(); |
| |
| QUnit.deepEqual(FTPInfo.serverResponses, ["150 Sending data\r\n"], |
| "unconsumed server responses"); |
| readFinalReply_().catch(function (error) { |
| QUnit.equal(error.message, "FTP protocol violation error", |
| "multiple 1yz replies caught"); |
| QUnit.equal(FTPInfo.preliminaryState, false, "reset preliminary state"); |
| QUnit.equal(FTPInfo.preliminaryRead, null, "reset preliminary read"); |
| QUnit.start(); |
| }) |
| }); |
| }); |
| |
| QUnit.test("onReceiveCallback_ preliminary responses error", function () { |
| expect(6); |
| var client = new FTPClient(MockSocket); |
| var FTPInfo = client.test.FTPInfo, |
| onReceiveCallback_ = client.test.onReceiveCallback_, |
| readReply_ = client.test.readReply_, |
| readFinalReply_ = client.test.readFinalReply_, |
| commandRawData = FTPInfo.commandRawData, encoder = new TextEncoder("utf-8"); |
| QUnit.stop(); |
| client.connect("cmu.edu", 22).then(function () { |
| QUnit.deepEqual(commandRawData.parsedLines, [], "reply consumed"); |
| QUnit.deepEqual(FTPInfo.serverResponses, [], "reply consumed"); |
| |
| var commandId = FTPInfo.commandId; |
| var sendData = encoder.encode("220 OK\r\n220 OK\r\n").buffer; |
| var sendInfo = {socketId: commandId, data: sendData}; |
| |
| onReceiveCallback_(sendInfo); |
| QUnit.deepEqual(FTPInfo.serverResponses, ["220 OK\r\n", "220 OK\r\n"], |
| "unconsumed server responses"); |
| readFinalReply_().catch(function (error) { |
| QUnit.equal(error.message, |
| "Final read requested in non-preliminary state"); |
| QUnit.equal(FTPInfo.preliminaryState, false, "reset preliminary state"); |
| QUnit.equal(FTPInfo.preliminaryRead, null, "reset preliminary read"); |
| QUnit.start(); |
| }) |
| }); |
| }); |
| |
| |
| QUnit.test("sendCommand_", function (assert) { |
| expect(10); |
| QUnit.stop(); |
| var client = new FTPClient(MockSocket); |
| var FTPInfo = client.test.FTPInfo, |
| sendCommand_ = client.test.sendCommand_; |
| client.connect("cmu.edu", 21).then(function (reply) { |
| QUnit.deepEqual(reply, "220 Service ready for new user\r\n", |
| "connection successful"); |
| return sendCommand_("USER anonymous\r\n"); |
| }).then(function (reply) { |
| QUnit.equal(reply, "331 User name okay, need password\r\n", |
| "got USER reply"); |
| return sendCommand_("USER\r\n"); |
| }).catch(function (error) { |
| QUnit.equal(error.message, "501 Syntax error in parameters or arguments\r\n", |
| "USER syntax error"); |
| return sendCommand_("INVALID\r\n"); |
| }).catch(function (error) { |
| QUnit.equal(error.message, "500 Unknown command\r\n", "Unknown command caught"); |
| return sendCommand_("\r\n"); |
| }).catch(function (error) { |
| QUnit.equal(error.message, "500 Unknown command\r\n"); |
| return sendCommand_("PASS chrome@example.com\r\n"); |
| }).catch(function (error) { |
| QUnit.equal(error.message, "530 Not logged in\r\n", "PASS was not preceded by USER"); |
| return sendCommand_("USER anonymous\r\n"); |
| }).then(function (reply) { |
| QUnit.equal(reply, "331 User name okay, need password\r\n"); |
| return sendCommand_("PASS chrome@example.com\r\n"); |
| }).then(function (reply) { |
| QUnit.equal(reply, "230 User logged in, proceed\r\n"); |
| return sendCommand_("PASV\r\n"); |
| }).then(function (reply) { |
| var n = reply.search("227 Entering passive mode"); |
| var re = /\d{1,3},\d{1,3},\d{1,3},\d{1,3},(\d{1,3}),(\d{1,3})/; |
| var hostPort = re.exec(reply); |
| QUnit.equal(n, 0, "passive mode reply returned"); |
| QUnit.ok(hostPort != null, "Host and port information sent"); |
| QUnit.start(); |
| }).catch(function (error) { |
| console.log(error); |
| QUnit.equal(error, "This test should have succeeded"); |
| QUnit.start(); |
| }); |
| }); |
| |
| QUnit.test("sendCommand errors", function () { |
| QUnit.stop(); |
| expect(1); |
| var client = new FTPClient(MockSocket); |
| var FTPInfo = client.test.FTPInfo, |
| sendCommand_ = client.test.sendCommand_; |
| // not connected, hence can't send commands! |
| sendCommand_("USER anonymous\r\n").then(function (reply) { |
| QUnit.equal(reply, "This should fail"); |
| QUnit.start(); |
| }).catch(function (error) { |
| QUnit.equal(error.message, "Error code -2", "send error caught"); |
| QUnit.start(); |
| }); |
| }); |
| |
| QUnit.test("parsePASV", function () { |
| expect(8); |
| var client = new FTPClient(MockSocket); |
| var FTPInfo = client.test.FTPInfo, parsePASVReply_ = client.test.parsePASVReply_; |
| var port = parsePASVReply_("227 Entering passive mode"); |
| QUnit.ok(port === null, "Invalid reply"); |
| |
| port = parsePASVReply_("227 Entering passive mode 13,15"); |
| QUnit.ok(port === null, "invalid reply"); |
| |
| port = parsePASVReply_("227 Entering passive mode 0,0,0,0,15,45"); |
| QUnit.equal(port, 15<<8 | 45, "valid port number received"); |
| |
| port = parsePASVReply_("227 Entering passive mode (0,0,0,0,15,45)"); |
| QUnit.equal(port, 15<<8 | 45, "valid port number received"); |
| |
| port = parsePASVReply_("227 Entering passive mode (0,0,0,0,15)"); |
| QUnit.ok(port === null, "invalid reply"); |
| |
| port = parsePASVReply_("227 Entering passive mode 000,0,0,0,1500,45"); |
| QUnit.ok(port === null, "invalid reply"); |
| |
| port = parsePASVReply_("227 Entering passive mode (0,0,0,0,300,45)"); |
| QUnit.ok(port === null, "invalid reply"); |
| |
| port = parsePASVReply_("227 Entering passive mode (0,0,0,0,300,450)"); |
| QUnit.ok(port === null, "invalid reply"); |
| }); |
| |
| QUnit.test("parseESPV_", function () { |
| var client = new FTPClient(MockSocket); |
| var FTPInfo = client.test.FTPInfo, parseEPSVReply_ = client.test.parseEPSVReply_; |
| var port = parseEPSVReply_("227 Entering passive mode"); |
| QUnit.ok(port === null, "Invalid reply"); |
| |
| port = parseEPSVReply_("227 Entering passive mode (13,15)"); |
| QUnit.ok(port === null, "invalid reply"); |
| |
| port = parseEPSVReply_("227 Entering passive mode (||1315)"); |
| QUnit.ok(port === null, "invalid reply"); |
| |
| port = parseEPSVReply_("227 Entering passive mode (|||1315)"); |
| QUnit.ok(port === null, "invalid reply"); |
| |
| port = parseEPSVReply_("227 Entering passive mode (|||13152|)"); |
| QUnit.ok(port == 13152, "invalid reply"); |
| |
| port = parseEPSVReply_("227 Entering passive mode |||13215|"); |
| QUnit.ok(port === null, "invalid reply"); |
| |
| port = parseEPSVReply_("227 Entering passive mode (13152|)"); |
| QUnit.ok(port === null, "invalid reply"); |
| |
| port = parseEPSVReply_("227 Entering passive mode 13215"); |
| QUnit.ok(port === null, "invalid reply"); |
| }); |
| |
| QUnit.test("dataConnect", function () { |
| QUnit.stop(); |
| expect(3); |
| var client = new FTPClient(MockSocket); |
| var FTPInfo = client.test.FTPInfo, dataConnect_ = client.test.dataConnect_; |
| client.connect("cmu.edu", 21).then(function (reply){ |
| QUnit.equal(reply, "220 Service ready for new user\r\n"); |
| return dataConnect_(); |
| }).then(function (connectInfo) { |
| QUnit.ok(connectInfo.socketId >= 0, "created data socket"); |
| QUnit.ok(connectInfo.port != null, "Got a data port from server"); |
| QUnit.start(); |
| }).catch(function (error) { |
| QUnit.equal(error, "This test should have succeeded"); |
| QUnit.start(); |
| }); |
| }); |
| |
| QUnit.test("login", function () { |
| QUnit.stop(); |
| expect(2); |
| var client = new FTPClient(MockSocket); |
| var FTPInfo = client.test.FTPInfo; |
| client.connect("cmu.edu", 21).then(function (reply) { |
| QUnit.equal(reply, "220 Service ready for new user\r\n"); |
| return client.login(); |
| }).then(function (reply) { |
| QUnit.equal(reply, "230 User logged in, proceed\r\n"); |
| QUnit.start(); |
| }); |
| }); |
| |
| QUnit.test("noop", function (pathname) { |
| QUnit.stop(); |
| expect(2); |
| var client = new FTPClient(MockSocket), noop_ = client.test.noop_; |
| client.connect("cmu.edu", 21).then(function (reply) { |
| QUnit.equal(reply, "220 Service ready for new user\r\n"); |
| return noop_(); |
| }).then(function (reply) { |
| QUnit.equal(reply, "220 OK\r\n"); |
| QUnit.start(); |
| }).catch(function (error) { |
| QUnit.equal(reply, "This test should have suceeded"); |
| QUnit.start(); |
| }); |
| }); |
| |
| QUnit.test("parsePWDReply_", function (pathname) { |
| expect(10); |
| var client = new FTPClient(MockSocket), |
| parsePWDReply_ = client.test.parsePWDReply_; |
| var dir = parsePWDReply_("227 \"/home/ftp/\"\r\n"); |
| QUnit.ok(dir == "/home/ftp/", "Parsed dir"); |
| |
| dir = parsePWDReply_("227 \"/home/ftp/\r\n"); |
| QUnit.ok(dir === null, "invalid reply"); |
| |
| dir = parsePWDReply_("227 \"/home/ftp\""); |
| QUnit.ok(dir == "/home/ftp/", "parsed dir"); |
| |
| dir = parsePWDReply_("227 /home/ftp/\r\n"); |
| QUnit.ok(dir == "/home/ftp/" , "parsed dir"); |
| |
| dir = parsePWDReply_("227 /home/ftp/"); |
| QUnit.ok(dir === null, "invalid reply"); |
| |
| dir = parsePWDReply_("227 \"/\""); |
| QUnit.ok(dir == "/", "parsed dir"); |
| |
| dir = parsePWDReply_("227 /home/ftp\r"); |
| QUnit.ok(dir == "/home/ftp/", "parsed dir"); |
| |
| dir = parsePWDReply_("227 /home/ftp\n"); |
| QUnit.ok(dir == "/home/ftp/", "parsed dir"); |
| |
| dir = parsePWDReply_("227\r\n"); |
| QUnit.ok(dir === null, "invalid reply"); |
| |
| dir = parsePWDReply_("227 \r\n"); |
| QUnit.ok(dir === null, "invalid reply"); |
| }); |
| |
| QUnit.test("getCurrentDir", function (pathname) { |
| QUnit.stop(); |
| expect(2); |
| var client = new FTPClient(MockSocket), |
| getCurrentDir = client.getCurrentDir; |
| client.connect("cmu.edu", 21).then(function (reply) { |
| QUnit.equal(reply, "220 Service ready for new user\r\n"); |
| return getCurrentDir(); |
| }).then(function (reply) { |
| QUnit.equal(reply, "/home/ftp/"); |
| QUnit.start(); |
| }).catch(function (error) { |
| QUnit.equal(error, "This test should have suceeded"); |
| QUnit.start(); |
| }); |
| }); |
| |
| QUnit.test("changeWorkingDir", function (pathname) { |
| QUnit.stop(); |
| expect(2); |
| var client = new FTPClient(MockSocket), |
| changeWorkingDir = client.changeWorkingDir; |
| client.connect("cmu.edu", 21).then(function (reply) { |
| QUnit.equal(reply, "220 Service ready for new user\r\n"); |
| return changeWorkingDir("/home/ftpclient/"); |
| }).then(function (reply) { |
| QUnit.equal(reply, "250 Directory changed\r\n"); |
| QUnit.start(); |
| }).catch(function (error) { |
| QUnit.equal(reply, "This test should have suceeded"); |
| QUnit.start(); |
| }); |
| }); |
| |
| QUnit.test("changeToParentDir", function (pathname) { |
| QUnit.stop(); |
| expect(2); |
| var client = new FTPClient(MockSocket), |
| changeToParentDir = client.changeToParentDir; |
| client.connect("cmu.edu", 21).then(function (reply) { |
| QUnit.equal(reply, "220 Service ready for new user\r\n"); |
| return changeToParentDir("/home/ftpclient/"); |
| }).then(function (reply) { |
| QUnit.equal(reply, "200 Directory changed\r\n"); |
| QUnit.start(); |
| }).catch(function (error) { |
| QUnit.equal(reply, "This test should have suceeded"); |
| QUnit.start(); |
| }); |
| }); |
| |
| |