1a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey/* 2a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey * Copyright (C) 2012 The Android Open Source Project 3a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey * 4a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey * Licensed under the Apache License, Version 2.0 (the "License"); 5a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey * you may not use this file except in compliance with the License. 6a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey * You may obtain a copy of the License at 7a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey * 8a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey * http://www.apache.org/licenses/LICENSE-2.0 9a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey * 10a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey * Unless required by applicable law or agreed to in writing, software 11a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey * distributed under the License is distributed on an "AS IS" BASIS, 12a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey * See the License for the specific language governing permissions and 14a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey * limitations under the License. 15a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey */ 16a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey 17a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkeypackage com.android.internal.util; 18a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey 19a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkeyimport static android.text.format.DateUtils.DAY_IN_MILLIS; 20a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkeyimport static android.text.format.DateUtils.HOUR_IN_MILLIS; 21a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkeyimport static android.text.format.DateUtils.MINUTE_IN_MILLIS; 22a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkeyimport static android.text.format.DateUtils.SECOND_IN_MILLIS; 23a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkeyimport static android.text.format.DateUtils.WEEK_IN_MILLIS; 24a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkeyimport static android.text.format.DateUtils.YEAR_IN_MILLIS; 25a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey 26a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkeyimport android.test.AndroidTestCase; 27a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkeyimport android.test.suitebuilder.annotation.Suppress; 28a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkeyimport android.util.Log; 29a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey 30a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkeyimport com.android.internal.util.FileRotator.Reader; 31a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkeyimport com.android.internal.util.FileRotator.Writer; 32a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkeyimport com.google.android.collect.Lists; 33a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey 34a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkeyimport java.io.DataInputStream; 35a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkeyimport java.io.DataOutputStream; 36a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkeyimport java.io.File; 37a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkeyimport java.io.FileOutputStream; 38a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkeyimport java.io.IOException; 39a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkeyimport java.io.InputStream; 40a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkeyimport java.io.OutputStream; 41a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkeyimport java.net.ProtocolException; 42a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkeyimport java.util.ArrayList; 43a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkeyimport java.util.Arrays; 44a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkeyimport java.util.Random; 45a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey 46bbf1861fdd2ba250354c060fe70f0ee7cbe93877Mikael Gullstrandimport junit.framework.Assert; 47bbf1861fdd2ba250354c060fe70f0ee7cbe93877Mikael Gullstrand 48a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkeyimport libcore.io.IoUtils; 49a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey 50a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey/** 51a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey * Tests for {@link FileRotator}. 52a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey */ 53a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkeypublic class FileRotatorTest extends AndroidTestCase { 54a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey private static final String TAG = "FileRotatorTest"; 55a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey 56a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey private File mBasePath; 57a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey 58a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey private static final String PREFIX = "rotator"; 59a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey private static final String ANOTHER_PREFIX = "another_rotator"; 60a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey 61a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey private static final long TEST_TIME = 1300000000000L; 62a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey 63a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey // TODO: test throwing rolls back correctly 64a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey 65a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey @Override 66a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey protected void setUp() throws Exception { 67a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey super.setUp(); 68a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey 69a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey mBasePath = getContext().getFilesDir(); 70a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey IoUtils.deleteContents(mBasePath); 71a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey } 72a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey 73a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey public void testEmpty() throws Exception { 74a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey final FileRotator rotate1 = new FileRotator( 75a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey mBasePath, PREFIX, DAY_IN_MILLIS, WEEK_IN_MILLIS); 76a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey final FileRotator rotate2 = new FileRotator( 77a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey mBasePath, ANOTHER_PREFIX, DAY_IN_MILLIS, WEEK_IN_MILLIS); 78a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey 79a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey final RecordingReader reader = new RecordingReader(); 80a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey long currentTime = TEST_TIME; 81a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey 82a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey // write single new value 83a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey rotate1.combineActive(reader, writer("foo"), currentTime); 84a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey reader.assertRead(); 85a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey 86a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey // assert that one rotator doesn't leak into another 87a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey assertReadAll(rotate1, "foo"); 88a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey assertReadAll(rotate2); 89a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey } 90a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey 91a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey public void testCombine() throws Exception { 92a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey final FileRotator rotate = new FileRotator( 93a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey mBasePath, PREFIX, DAY_IN_MILLIS, WEEK_IN_MILLIS); 94a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey 95a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey final RecordingReader reader = new RecordingReader(); 96a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey long currentTime = TEST_TIME; 97a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey 98a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey // first combine should have empty read, but still write data. 99a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey rotate.combineActive(reader, writer("foo"), currentTime); 100a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey reader.assertRead(); 101a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey assertReadAll(rotate, "foo"); 102a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey 103a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey // second combine should replace contents; should read existing data, 104a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey // and write final data to disk. 105a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey currentTime += SECOND_IN_MILLIS; 106a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey reader.reset(); 107a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey rotate.combineActive(reader, writer("bar"), currentTime); 108a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey reader.assertRead("foo"); 109a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey assertReadAll(rotate, "bar"); 110a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey } 111a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey 112a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey public void testRotate() throws Exception { 113a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey final FileRotator rotate = new FileRotator( 114a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey mBasePath, PREFIX, DAY_IN_MILLIS, WEEK_IN_MILLIS); 115a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey 116a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey final RecordingReader reader = new RecordingReader(); 117a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey long currentTime = TEST_TIME; 118a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey 119a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey // combine first record into file 120a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey rotate.combineActive(reader, writer("foo"), currentTime); 121a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey reader.assertRead(); 122a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey assertReadAll(rotate, "foo"); 123a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey 124a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey // push time a few minutes forward; shouldn't rotate file 125a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey reader.reset(); 126a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey currentTime += MINUTE_IN_MILLIS; 127a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey rotate.combineActive(reader, writer("bar"), currentTime); 128a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey reader.assertRead("foo"); 129a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey assertReadAll(rotate, "bar"); 130a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey 131a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey // push time forward enough to rotate file; should still have same data 132a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey currentTime += DAY_IN_MILLIS + SECOND_IN_MILLIS; 133a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey rotate.maybeRotate(currentTime); 134a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey assertReadAll(rotate, "bar"); 135a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey 136a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey // combine a second time, should leave rotated value untouched, and 137a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey // active file should be empty. 138a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey reader.reset(); 139a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey rotate.combineActive(reader, writer("baz"), currentTime); 140a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey reader.assertRead(); 141a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey assertReadAll(rotate, "bar", "baz"); 142a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey } 143a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey 144a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey public void testDelete() throws Exception { 145a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey final FileRotator rotate = new FileRotator( 146a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey mBasePath, PREFIX, MINUTE_IN_MILLIS, DAY_IN_MILLIS); 147a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey 148a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey final RecordingReader reader = new RecordingReader(); 149a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey long currentTime = TEST_TIME; 150a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey 151a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey // create first record and trigger rotating it 152a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey rotate.combineActive(reader, writer("foo"), currentTime); 153a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey reader.assertRead(); 154a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey currentTime += MINUTE_IN_MILLIS + SECOND_IN_MILLIS; 155a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey rotate.maybeRotate(currentTime); 156a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey 157a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey // create second record 158a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey reader.reset(); 159a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey rotate.combineActive(reader, writer("bar"), currentTime); 160a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey reader.assertRead(); 161a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey assertReadAll(rotate, "foo", "bar"); 162a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey 163a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey // push time far enough to expire first record 164a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey currentTime = TEST_TIME + DAY_IN_MILLIS + (2 * MINUTE_IN_MILLIS); 165a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey rotate.maybeRotate(currentTime); 166a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey assertReadAll(rotate, "bar"); 167a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey 168a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey // push further to delete second record 169a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey currentTime += WEEK_IN_MILLIS; 170a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey rotate.maybeRotate(currentTime); 171a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey assertReadAll(rotate); 172a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey } 173a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey 174a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey public void testThrowRestoresBackup() throws Exception { 175a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey final FileRotator rotate = new FileRotator( 176a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey mBasePath, PREFIX, MINUTE_IN_MILLIS, DAY_IN_MILLIS); 177a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey 178a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey final RecordingReader reader = new RecordingReader(); 179a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey long currentTime = TEST_TIME; 180a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey 181a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey // first, write some valid data 182a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey rotate.combineActive(reader, writer("foo"), currentTime); 183a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey reader.assertRead(); 184a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey assertReadAll(rotate, "foo"); 185a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey 186a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey try { 187a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey // now, try writing which will throw 188a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey reader.reset(); 189a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey rotate.combineActive(reader, new Writer() { 190a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey public void write(OutputStream out) throws IOException { 191a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey new DataOutputStream(out).writeUTF("bar"); 1926de357e4d10fa5977ab9a6c665dc858765e95d34Jeff Sharkey throw new NullPointerException("yikes"); 193a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey } 194a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey }, currentTime); 195a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey 196a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey fail("woah, somehow able to write exception"); 1976de357e4d10fa5977ab9a6c665dc858765e95d34Jeff Sharkey } catch (IOException e) { 198a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey // expected from above 199a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey } 200a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey 201a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey // assert that we read original data, and that it's still intact after 202a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey // the failed write above. 203a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey reader.assertRead("foo"); 204a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey assertReadAll(rotate, "foo"); 205a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey } 206a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey 207a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey public void testOtherFilesAndMalformed() throws Exception { 208a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey final FileRotator rotate = new FileRotator( 209a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey mBasePath, PREFIX, SECOND_IN_MILLIS, SECOND_IN_MILLIS); 210a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey 211a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey // should ignore another prefix 212a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey touch("another_rotator.1024"); 213a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey touch("another_rotator.1024-2048"); 214a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey assertReadAll(rotate); 215a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey 216a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey // verify that broken filenames don't crash 217a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey touch("rotator"); 218a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey touch("rotator..."); 219a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey touch("rotator.-"); 220a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey touch("rotator.---"); 221a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey touch("rotator.a-b"); 222a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey touch("rotator_but_not_actually"); 223a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey assertReadAll(rotate); 224a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey 225a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey // and make sure that we can read something from a legit file 226a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey write("rotator.100-200", "meow"); 227a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey assertReadAll(rotate, "meow"); 228a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey } 229a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey 230a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey private static final String RED = "red"; 231a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey private static final String GREEN = "green"; 232a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey private static final String BLUE = "blue"; 233a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey private static final String YELLOW = "yellow"; 234a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey 235a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey public void testQueryMatch() throws Exception { 236a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey final FileRotator rotate = new FileRotator( 237a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey mBasePath, PREFIX, HOUR_IN_MILLIS, YEAR_IN_MILLIS); 238a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey 239a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey final RecordingReader reader = new RecordingReader(); 240a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey long currentTime = TEST_TIME; 241a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey 242a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey // rotate a bunch of historical data 243a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey rotate.maybeRotate(currentTime); 244a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey rotate.combineActive(reader, writer(RED), currentTime); 245a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey 246a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey currentTime += DAY_IN_MILLIS; 247a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey rotate.maybeRotate(currentTime); 248a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey rotate.combineActive(reader, writer(GREEN), currentTime); 249a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey 250a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey currentTime += DAY_IN_MILLIS; 251a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey rotate.maybeRotate(currentTime); 252a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey rotate.combineActive(reader, writer(BLUE), currentTime); 253a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey 254a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey currentTime += DAY_IN_MILLIS; 255a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey rotate.maybeRotate(currentTime); 256a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey rotate.combineActive(reader, writer(YELLOW), currentTime); 257a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey 258a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey final String[] FULL_SET = { RED, GREEN, BLUE, YELLOW }; 259a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey 260a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey assertReadAll(rotate, FULL_SET); 261a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey assertReadMatching(rotate, Long.MIN_VALUE, Long.MAX_VALUE, FULL_SET); 262a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey assertReadMatching(rotate, Long.MIN_VALUE, currentTime, FULL_SET); 263a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey assertReadMatching(rotate, TEST_TIME + SECOND_IN_MILLIS, currentTime, FULL_SET); 264a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey 265a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey // should omit last value, since it only touches at currentTime 266a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey assertReadMatching(rotate, TEST_TIME + SECOND_IN_MILLIS, currentTime - SECOND_IN_MILLIS, 267a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey RED, GREEN, BLUE); 268a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey 269a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey // check boundary condition 270a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey assertReadMatching(rotate, TEST_TIME + DAY_IN_MILLIS, Long.MAX_VALUE, FULL_SET); 271a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey assertReadMatching(rotate, TEST_TIME + DAY_IN_MILLIS + SECOND_IN_MILLIS, Long.MAX_VALUE, 272a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey GREEN, BLUE, YELLOW); 273a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey 274a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey // test range smaller than file 275a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey final long blueStart = TEST_TIME + (DAY_IN_MILLIS * 2); 276a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey final long blueEnd = TEST_TIME + (DAY_IN_MILLIS * 3); 277a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey assertReadMatching(rotate, blueStart + SECOND_IN_MILLIS, blueEnd - SECOND_IN_MILLIS, BLUE); 278a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey 279a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey // outside range should return nothing 280a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey assertReadMatching(rotate, Long.MIN_VALUE, TEST_TIME - DAY_IN_MILLIS); 281a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey } 282a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey 283a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey public void testClockRollingBackwards() throws Exception { 284a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey final FileRotator rotate = new FileRotator( 285a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey mBasePath, PREFIX, DAY_IN_MILLIS, YEAR_IN_MILLIS); 286a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey 287a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey final RecordingReader reader = new RecordingReader(); 288a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey long currentTime = TEST_TIME; 289a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey 290a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey // create record at current time 291a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey // --> foo 292a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey rotate.combineActive(reader, writer("foo"), currentTime); 293a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey reader.assertRead(); 294a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey assertReadAll(rotate, "foo"); 295a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey 296a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey // record a day in past; should create a new active file 297a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey // --> bar 298a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey currentTime -= DAY_IN_MILLIS; 299a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey reader.reset(); 300a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey rotate.combineActive(reader, writer("bar"), currentTime); 301a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey reader.assertRead(); 302a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey assertReadAll(rotate, "bar", "foo"); 303a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey 304a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey // verify that we rewrite current active file 305a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey // bar --> baz 306a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey currentTime += SECOND_IN_MILLIS; 307a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey reader.reset(); 308a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey rotate.combineActive(reader, writer("baz"), currentTime); 309a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey reader.assertRead("bar"); 310a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey assertReadAll(rotate, "baz", "foo"); 311a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey 312a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey // return to present and verify we write oldest active file 313a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey // baz --> meow 314a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey currentTime = TEST_TIME + SECOND_IN_MILLIS; 315a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey reader.reset(); 316a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey rotate.combineActive(reader, writer("meow"), currentTime); 317a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey reader.assertRead("baz"); 318a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey assertReadAll(rotate, "meow", "foo"); 319a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey 320a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey // current time should trigger rotate of older active file 321a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey rotate.maybeRotate(currentTime); 322a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey 323a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey // write active file, verify this time we touch original 324a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey // foo --> yay 325a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey reader.reset(); 326a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey rotate.combineActive(reader, writer("yay"), currentTime); 327a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey reader.assertRead("foo"); 328a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey assertReadAll(rotate, "meow", "yay"); 329a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey } 330a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey 331a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey @Suppress 332a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey public void testFuzz() throws Exception { 333a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey final FileRotator rotate = new FileRotator( 334a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey mBasePath, PREFIX, HOUR_IN_MILLIS, DAY_IN_MILLIS); 335a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey 336a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey final RecordingReader reader = new RecordingReader(); 337a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey long currentTime = TEST_TIME; 338a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey 339a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey // walk forward through time, ensuring that files are cleaned properly 340a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey final Random random = new Random(); 341a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey for (int i = 0; i < 1024; i++) { 342a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey currentTime += Math.abs(random.nextLong()) % DAY_IN_MILLIS; 343a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey 344a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey reader.reset(); 345a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey rotate.combineActive(reader, writer("meow"), currentTime); 346a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey 347a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey if (random.nextBoolean()) { 348a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey rotate.maybeRotate(currentTime); 349a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey } 350a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey } 351a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey 352a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey rotate.maybeRotate(currentTime); 353a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey 354a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey Log.d(TAG, "currentTime=" + currentTime); 355a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey Log.d(TAG, Arrays.toString(mBasePath.list())); 356a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey } 357a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey 358a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey public void testRecoverAtomic() throws Exception { 359a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey write("rotator.1024-2048", "foo"); 360a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey write("rotator.1024-2048.backup", "bar"); 361a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey write("rotator.2048-4096", "baz"); 362a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey write("rotator.2048-4096.no_backup", ""); 363a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey 364a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey final FileRotator rotate = new FileRotator( 365a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey mBasePath, PREFIX, SECOND_IN_MILLIS, SECOND_IN_MILLIS); 366a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey 367a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey // verify backup value was recovered; no_backup indicates that 368a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey // corresponding file had no backup and should be discarded. 369a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey assertReadAll(rotate, "bar"); 370a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey } 371a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey 372bbf1861fdd2ba250354c060fe70f0ee7cbe93877Mikael Gullstrand public void testFileSystemInaccessible() throws Exception { 373bbf1861fdd2ba250354c060fe70f0ee7cbe93877Mikael Gullstrand File inaccessibleDir = null; 374bbf1861fdd2ba250354c060fe70f0ee7cbe93877Mikael Gullstrand String dirPath = getContext().getFilesDir() + File.separator + "inaccessible"; 375bbf1861fdd2ba250354c060fe70f0ee7cbe93877Mikael Gullstrand inaccessibleDir = new File(dirPath); 376bbf1861fdd2ba250354c060fe70f0ee7cbe93877Mikael Gullstrand final FileRotator rotate = new FileRotator(inaccessibleDir, PREFIX, SECOND_IN_MILLIS, SECOND_IN_MILLIS); 377bbf1861fdd2ba250354c060fe70f0ee7cbe93877Mikael Gullstrand 378bbf1861fdd2ba250354c060fe70f0ee7cbe93877Mikael Gullstrand // rotate should not throw on dir not mkdir-ed (or otherwise inaccessible) 379bbf1861fdd2ba250354c060fe70f0ee7cbe93877Mikael Gullstrand rotate.maybeRotate(TEST_TIME); 380bbf1861fdd2ba250354c060fe70f0ee7cbe93877Mikael Gullstrand } 381bbf1861fdd2ba250354c060fe70f0ee7cbe93877Mikael Gullstrand 382a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey private void touch(String... names) throws IOException { 383a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey for (String name : names) { 384a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey final OutputStream out = new FileOutputStream(new File(mBasePath, name)); 385a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey out.close(); 386a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey } 387a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey } 388a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey 389a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey private void write(String name, String value) throws IOException { 390a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey final DataOutputStream out = new DataOutputStream( 391a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey new FileOutputStream(new File(mBasePath, name))); 392a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey out.writeUTF(value); 393a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey out.close(); 394a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey } 395a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey 396a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey private static Writer writer(final String value) { 397a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey return new Writer() { 398a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey public void write(OutputStream out) throws IOException { 399a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey new DataOutputStream(out).writeUTF(value); 400a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey } 401a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey }; 402a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey } 403a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey 404a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey private static void assertReadAll(FileRotator rotate, String... expected) throws IOException { 405a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey assertReadMatching(rotate, Long.MIN_VALUE, Long.MAX_VALUE, expected); 406a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey } 407a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey 408a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey private static void assertReadMatching( 409a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey FileRotator rotate, long matchStartMillis, long matchEndMillis, String... expected) 410a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey throws IOException { 411a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey final RecordingReader reader = new RecordingReader(); 412a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey rotate.readMatching(reader, matchStartMillis, matchEndMillis); 413a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey reader.assertRead(expected); 414a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey } 415a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey 416a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey private static class RecordingReader implements Reader { 417a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey private ArrayList<String> mActual = Lists.newArrayList(); 418a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey 419a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey public void read(InputStream in) throws IOException { 420a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey mActual.add(new DataInputStream(in).readUTF()); 421a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey } 422a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey 423a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey public void reset() { 424a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey mActual.clear(); 425a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey } 426a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey 427a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey public void assertRead(String... expected) { 428a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey assertEquals(expected.length, mActual.size()); 429a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey 430a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey final ArrayList<String> actualCopy = new ArrayList<String>(mActual); 431a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey for (String value : expected) { 432a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey if (!actualCopy.remove(value)) { 433a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey final String expectedString = Arrays.toString(expected); 434a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey final String actualString = Arrays.toString(mActual.toArray()); 435a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey fail("expected: " + expectedString + " but was: " + actualString); 436a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey } 437a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey } 438a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey } 439a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey } 440a27a3e8ad7d20dea63ef2d5cb8b6ec7e56c20a89Jeff Sharkey} 441