// Copyright 2011 The Closure Library Authors. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS-IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. goog.provide('goog.testing.fs.FileWriterTest'); goog.setTestOnly('goog.testing.fs.FileWriterTest'); goog.require('goog.async.Deferred'); goog.require('goog.events'); goog.require('goog.fs.Error'); goog.require('goog.fs.FileSaver'); goog.require('goog.testing.AsyncTestCase'); goog.require('goog.testing.MockClock'); goog.require('goog.testing.fs.Blob'); goog.require('goog.testing.fs.FileSystem'); goog.require('goog.testing.jsunit'); var asyncTestCase = goog.testing.AsyncTestCase.createAndInstall(); var file, deferredWriter, mockClock; function setUp() { mockClock = new goog.testing.MockClock(true); var fs = new goog.testing.fs.FileSystem(); var fileEntry = fs.getRoot().createDirectorySync('foo').createFileSync('bar'); deferredWriter = fileEntry.createWriter(); file = fileEntry.fileSync(); file.setDataInternal(''); } function tearDown() { mockClock.uninstall(); } function testWrite() { deferredWriter. addCallback(goog.partial(checkReadyState, goog.fs.FileSaver.ReadyState.INIT)). addCallback(goog.partial(checkPositionAndLength, 0, 0)). addCallback(goog.partial(checkLastModified, 0)). addCallback(goog.partial(tick, 3)). addCallback(goog.partial(writeString, 'hello')). addCallback(goog.partial(checkPositionAndLength, 0, 0)). addCallback(goog.partial(checkReadyState, goog.fs.FileSaver.ReadyState.WRITING)). addCallback(goog.partial(checkLastModified, 0)). addCallback(goog.partial(waitForEvent, goog.fs.FileSaver.EventType.WRITE_START)). addCallback(goog.partial(checkLastModified, 0)). addCallback(goog.partial(checkPositionAndLength, 0, 0)). addCallback(goog.partial(waitForEvent, goog.fs.FileSaver.EventType.WRITE)). addCallback(function() { assertEquals('hello', file.toString()); }). addCallback(goog.partial(checkPositionAndLength, 5, 5)). addCallback(goog.partial(checkLastModified, 3)). addCallback(tick). addCallback(goog.partial(checkReadyState, goog.fs.FileSaver.ReadyState.WRITING)). addCallback(goog.partial(checkLastModified, 3)). addCallback(goog.partial(waitForEvent, goog.fs.FileSaver.EventType.WRITE_END)). addCallback(goog.partial(checkLastModified, 3)). addCallback(goog.partial(checkReadyState, goog.fs.FileSaver.ReadyState.DONE)). addCallback(goog.partial(checkLastModified, 3)). addCallback(goog.partial(writeString, ' world')). addCallback(goog.partial(checkPositionAndLength, 5, 5)). addCallback(goog.partial(waitForEvent, goog.fs.FileSaver.EventType.WRITE)). addCallback(function() { assertEquals('hello world', file.toString()); }). addCallback(goog.partial(checkPositionAndLength, 11, 11)). addCallback(goog.partial(checkLastModified, 4)). addBoth(continueTesting); waitForAsync('testWrite'); } function testSeek() { deferredWriter. addCallback(goog.partial(tick, 17)). addCallback(goog.partial(writeAndWait, 'hello world')). addCallback(tick). addCallback(goog.partial(checkPositionAndLength, 11, 11)). addCallback(function(writer) { writer.seek(6); }). addCallback(goog.partial(checkPositionAndLength, 6, 11)). addCallback(goog.partial(checkLastModified, 17)). addCallback(goog.partial(writeAndWait, 'universe')). addCallback(tick). addCallback(function() { assertEquals('hello universe', file.toString()); }). addCallback(goog.partial(checkPositionAndLength, 14, 14)). addCallback(function(writer) { writer.seek(500); }). addCallback(goog.partial(checkPositionAndLength, 14, 14)). addCallback(goog.partial(writeAndWait, '!')). addCallback(tick). addCallback(function() { assertEquals('hello universe!', file.toString()); }). addCallback(goog.partial(checkPositionAndLength, 15, 15)). addCallback(function(writer) { writer.seek(-9); }). addCallback(goog.partial(checkPositionAndLength, 6, 15)). addCallback(goog.partial(writeAndWait, 'foo')). addCallback(tick). addCallback(function() { assertEquals('hello fooverse!', file.toString()); }). addCallback(goog.partial(checkPositionAndLength, 9, 15)). addCallback(function(writer) { writer.seek(-500); }). addCallback(goog.partial(checkPositionAndLength, 0, 15)). addCallback(goog.partial(writeAndWait, 'bye-o')). addCallback(tick). addCallback(function() { assertEquals('bye-o fooverse!', file.toString()); }). addCallback(goog.partial(checkPositionAndLength, 5, 15)). addCallback(goog.partial(checkLastModified, 21)). addBoth(continueTesting); waitForAsync('testSeek'); } function testAbort() { deferredWriter. addCallback(goog.partial(tick, 13)). addCallback(goog.partial(writeString, 'hello world')). addCallback(function(writer) { writer.abort(); }). addCallback(goog.partial(checkReadyState, goog.fs.FileSaver.ReadyState.WRITING)). addCallback(goog.partial(waitForError, goog.fs.Error.ErrorCode.ABORT)). addCallback(goog.partial(checkReadyState, goog.fs.FileSaver.ReadyState.WRITING)). addCallback(goog.partial(waitForEvent, goog.fs.FileSaver.EventType.ABORT)). addCallback(goog.partial(checkReadyState, goog.fs.FileSaver.ReadyState.WRITING)). addCallback(goog.partial(waitForEvent, goog.fs.FileSaver.EventType.WRITE_END)). addCallback(goog.partial(checkReadyState, goog.fs.FileSaver.ReadyState.DONE)). addCallback(goog.partial(checkPositionAndLength, 0, 0)). addCallback(goog.partial(checkLastModified, 0)). addCallback(function() { assertEquals('', file.toString()); }). addBoth(continueTesting); waitForAsync('testAbort'); } function testTruncate() { deferredWriter. addCallback(goog.partial(writeAndWait, 'hello world')). addCallback(goog.partial(checkPositionAndLength, 11, 11)). addCallback(function(writer) { writer.truncate(5); }). addCallback(goog.partial(checkPositionAndLength, 11, 11)). addCallback(goog.partial(checkReadyState, goog.fs.FileSaver.ReadyState.WRITING)). addCallback(goog.partial(waitForEvent, goog.fs.FileSaver.EventType.WRITE_START)). addCallback(goog.partial(tick, 7)). addCallback(goog.partial(checkPositionAndLength, 11, 11)). addCallback(goog.partial(checkLastModified, 0)). addCallback(goog.partial(waitForEvent, goog.fs.FileSaver.EventType.WRITE)). addCallback(goog.partial(checkLastModified, 7)). addCallback(tick). addCallback(goog.partial(checkReadyState, goog.fs.FileSaver.ReadyState.WRITING)). addCallback(goog.partial(checkPositionAndLength, 5, 5)). addCallback(function() { assertEquals('hello', file.toString()); }). addCallback(goog.partial(waitForEvent, goog.fs.FileSaver.EventType.WRITE_END)). addCallback(goog.partial(checkReadyState, goog.fs.FileSaver.ReadyState.DONE)). addCallback(function(writer) { writer.truncate(10); }). addCallback(goog.partial(waitForEvent, goog.fs.FileSaver.EventType.WRITE_END)). addCallback(goog.partial(checkPositionAndLength, 5, 10)). addCallback(goog.partial(checkLastModified, 8)). addCallback(function() { assertEquals('hello\0\0\0\0\0', file.toString()); }). addBoth(continueTesting); waitForAsync('testTruncate'); } function testAbortBeforeWrite() { deferredWriter. addCallback(function(writer) { writer.abort(); }). addErrback(function(err) { assertEquals(goog.fs.Error.ErrorCode.INVALID_STATE, err.code); return true; }). addCallback(function(calledErrback) { assertTrue(calledErrback); }). addBoth(continueTesting); waitForAsync('testAbortBeforeWrite'); } function testAbortAfterWrite() { deferredWriter. addCallback(goog.partial(writeAndWait, 'hello world')). addCallback(function(writer) { writer.abort(); }). addErrback(function(err) { assertEquals(goog.fs.Error.ErrorCode.INVALID_STATE, err.code); return true; }). addCallback(assertTrue). addBoth(continueTesting); waitForAsync('testAbortAfterWrite'); } function testWriteDuringWrite() { deferredWriter. addCallback(goog.partial(writeString, 'hello world')). addCallback(goog.partial(writeString, 'hello world')). addErrback(function(err) { assertEquals(goog.fs.Error.ErrorCode.INVALID_STATE, err.code); return true; }). addCallback(assertTrue). addBoth(continueTesting); waitForAsync('testWriteDuringWrite'); } function testSeekDuringWrite() { deferredWriter. addCallback(goog.partial(writeString, 'hello world')). addCallback(function(writer) { writer.seek(5); }). addErrback(function(err) { assertEquals(goog.fs.Error.ErrorCode.INVALID_STATE, err.code); return true; }). addCallback(assertTrue). addBoth(continueTesting); waitForAsync('testSeekDuringWrite'); } function testTruncateDuringWrite() { deferredWriter. addCallback(goog.partial(writeString, 'hello world')). addCallback(function(writer) { writer.truncate(5); }). addErrback(function(err) { assertEquals(goog.fs.Error.ErrorCode.INVALID_STATE, err.code); return true; }). addCallback(assertTrue). addBoth(continueTesting); waitForAsync('testTruncateDuringWrite'); } function tick(opt_tickCount) { mockClock.tick(opt_tickCount); } function continueTesting(result) { asyncTestCase.continueTesting(); if (result instanceof Error) { throw result; } mockClock.tick(); } function waitForAsync(msg) { asyncTestCase.waitForAsync(msg); // The mock clock must be advanced far enough that all timeouts added during // callbacks will be triggered. 1000ms is much more than enough. mockClock.tick(1000); } function waitForEvent(type, target) { var d = new goog.async.Deferred(); goog.events.listenOnce(target, type, goog.bind(d.callback, d, target)); return d; } function waitForError(type, target) { var d = new goog.async.Deferred(); goog.events.listenOnce( target, goog.fs.FileSaver.EventType.ERROR, function(e) { assertEquals(type, target.getError().code); d.callback(target); }); return d; } function checkReadyState(expectedState, writer) { assertEquals(expectedState, writer.getReadyState()); } function checkPositionAndLength(expectedPosition, expectedLength, writer) { assertEquals(expectedPosition, writer.getPosition()); assertEquals(expectedLength, writer.getLength()); } function checkLastModified(expectedTime) { assertEquals(expectedTime, file.lastModifiedDate.getTime()); } function writeString(str, writer) { writer.write(new goog.testing.fs.Blob(str)); } function writeAndWait(str, writer) { writeString(str, writer); return waitForEvent(goog.fs.FileSaver.EventType.WRITE_END, writer); }