/*
* Copyright 2015 Red Hat, Inc. and/or its affiliates.
*
* 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.
*/
package org.uberfire.io.impl;
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URI;
import java.util.HashMap;
import java.util.List;
import java.util.Random;
import org.apache.commons.io.FileUtils;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
import org.mockito.Mockito;
import org.uberfire.commons.lifecycle.PriorityDisposableRegistry;
import org.uberfire.io.CommonIOServiceDotFileTest;
import org.uberfire.io.IOService;
import org.uberfire.java.nio.base.options.CommentedOption;
import org.uberfire.java.nio.base.version.VersionAttributeView;
import org.uberfire.java.nio.file.FileSystem;
import org.uberfire.java.nio.file.Path;
import org.uberfire.java.nio.file.WatchEvent;
import org.uberfire.java.nio.file.WatchService;
import org.uberfire.java.nio.file.api.FileSystemProviders;
import org.uberfire.java.nio.fs.jgit.JGitFileSystem;
import org.uberfire.java.nio.fs.jgit.JGitFileSystemProvider;
import static org.junit.Assert.*;
import static org.mockito.Mockito.*;
public class BatchTest {
final static IOService ioService = new IOServiceDotFileImpl();
static FileSystem fs1;
static JGitFileSystem fs1Batch;
static FileSystem fs2;
static JGitFileSystem fs2Batch;
static FileSystem fs3;
static JGitFileSystem fs3Batch;
private static File path = null;
@BeforeClass
public static void setup() throws IOException {
assertTrue(PriorityDisposableRegistry.getDisposables().contains(ioService));
path = CommonIOServiceDotFileTest.createTempDirectory();
// XXX this is shaky at best: FileSystemProviders bootstraps the JGit FS in a static initializer.
// if anything has referenced it before now, setting this system property will have no effect.
System.setProperty("org.uberfire.nio.git.dir",
path.getAbsolutePath());
System.out.println(".niogit: " + path.getAbsolutePath());
final URI newRepo = URI.create("git://amend-repo-test");
fs1 = ioService.newFileSystem(newRepo,
new HashMap<String, Object>());
fs1Batch = (JGitFileSystem) fs1;
Path init = ioService.get(URI.create("git://amend-repo-test/init.file"));
ioService.write(init,
"setupFS!");
final URI newRepo2 = URI.create("git://check-amend-repo-test");
fs2 = ioService.newFileSystem(newRepo2,
new HashMap<String, Object>() {{
put("init",
"true");
}});
fs2Batch = (JGitFileSystem) fs2;
init = ioService.get(URI.create("git://check-amend-repo-test/init.file"));
ioService.write(init,
"setupFS!");
final URI newRepo3 = URI.create("git://check-amend-repo-test-2");
fs3 = ioService.newFileSystem(newRepo3,
new HashMap<String, Object>() {{
put("init",
"true");
}});
fs3Batch = (JGitFileSystem) fs3;
init = ioService.get(URI.create("git://check-amend-repo-test-2/init.file"));
ioService.write(init,
"setupFS!");
}
@AfterClass
public static void cleanup() {
FileUtils.deleteQuietly(path);
JGitFileSystemProvider gitFsProvider = (JGitFileSystemProvider) FileSystemProviders.resolveProvider(URI.create("git://whatever"));
gitFsProvider.shutdown();
FileUtils.deleteQuietly(gitFsProvider.getGitRepoContainerDir());
gitFsProvider.rescanForExistingRepositories();
}
@Test
public void testBatch() throws IOException, InterruptedException {
final Path init = ioService.get(URI.create("git://amend-repo-test/readme.txt"));
final WatchService ws = init.getFileSystem().newWatchService();
ioService.write(init,
"init!",
new CommentedOption("User Tester",
"message1"));
ioService.write(init,
"init 2!",
new CommentedOption("User Tester",
"message2"));
{
List<WatchEvent<?>> events = ws.poll().pollEvents();
assertEquals(1,
events.size());//modify readme
}
final Path init2 = ioService.get(URI.create("git://amend-repo-test/readme2.txt"));
ioService.write(init2,
"init 3!",
new CommentedOption("User Tester",
"message3"));
{
List<WatchEvent<?>> events = ws.poll().pollEvents();
assertEquals(1,
events.size()); // add file
}
ioService.write(init2,
"init 4!",
new CommentedOption("User Tester",
"message4"));
{
List<WatchEvent<?>> events = ws.poll().pollEvents();
assertEquals(1,
events.size());// modify file
}
final VersionAttributeView vinit = ioService.getFileAttributeView(init,
VersionAttributeView.class);
final VersionAttributeView vinit2 = ioService.getFileAttributeView(init,
VersionAttributeView.class);
assertEquals("init 2!",
ioService.readAllString(init));
assertNotNull(vinit);
assertEquals(2,
vinit.readAttributes().history().records().size());
assertNotNull(vinit2);
assertEquals(2,
vinit2.readAttributes().history().records().size());
ioService.startBatch(new FileSystem[]{init.getFileSystem()});
final Path path = ioService.get(URI.create("git://amend-repo-test/mybatch" + new Random(10L).nextInt() + ".txt"));
final Path path2 = ioService.get(URI.create("git://amend-repo-test/mybatch2" + new Random(10L).nextInt() + ".txt"));
ioService.write(path,
"ooooo!");
//init.file event
assertNotNull(ws.poll());
ioService.write(path,
"ooooo wdfs fg sdf!");
assertNull(ws.poll());
ioService.write(path2,
"ooooo222!");
assertNull(ws.poll());
ioService.write(path2,
" sdfsdg sdg ooooo222!");
assertNull(ws.poll());
ioService.endBatch();
{
List<WatchEvent<?>> events = ws.poll().pollEvents();
assertEquals(2,
events.size()); //adds files
}
final VersionAttributeView v = ioService.getFileAttributeView(path,
VersionAttributeView.class);
final VersionAttributeView v2 = ioService.getFileAttributeView(path2,
VersionAttributeView.class);
assertNotNull(v);
assertNotNull(v2);
assertEquals(1,
v.readAttributes().history().records().size());
assertEquals(1,
v2.readAttributes().history().records().size());
}
@Test
public void testBatch2() throws IOException, InterruptedException {
final Path f1 = ioService.get(URI.create("git://check-amend-repo-test/f1.txt"));
final Path f2 = ioService.get(URI.create("git://check-amend-repo-test/f2.txt"));
final Path f3 = ioService.get(URI.create("git://check-amend-repo-test/f3.txt"));
// XXX: Workaround for UF-70: amend-test-repo has to contain something so it can receive the BATCH
ioService.write(f1,
"init f1!");
ioService.write(f2,
"init f2!");
// END workaround
final WatchService ws = f1.getFileSystem().newWatchService();
ioService.startBatch(new FileSystem[]{f1.getFileSystem()});
ioService.write(f1,
"f1-u1!");
assertNull(ws.poll());
ioService.write(f2,
"f2-u1!");
assertNull(ws.poll());
ioService.write(f3,
"f3-u1!");
assertNull(ws.poll());
ioService.endBatch();
{
List<WatchEvent<?>> events = ws.poll().pollEvents();
assertEquals(3,
events.size()); //adds files
final VersionAttributeView v = ioService.getFileAttributeView(f1,
VersionAttributeView.class);
assertNotNull(v);
assertEquals(2,
v.readAttributes().history().records().size());
final VersionAttributeView v2 = ioService.getFileAttributeView(f2,
VersionAttributeView.class);
assertNotNull(v2);
assertEquals(2,
v2.readAttributes().history().records().size());
final VersionAttributeView v3 = ioService.getFileAttributeView(f3,
VersionAttributeView.class);
assertNotNull(v3);
assertEquals(1,
v3.readAttributes().history().records().size());
}
ioService.startBatch(new FileSystem[]{f1.getFileSystem()});
ioService.write(f1,
"f1-u1!");
assertNull(ws.poll());
ioService.write(f2,
"f2-u2!");
assertNull(ws.poll());
ioService.write(f3,
"f3-u2!");
assertNull(ws.poll());
ioService.endBatch();
{
List<WatchEvent<?>> events = ws.poll().pollEvents();
assertEquals(2,
events.size()); //adds files
final VersionAttributeView v = ioService.getFileAttributeView(f1,
VersionAttributeView.class);
assertNotNull(v);
assertEquals(2,
v.readAttributes().history().records().size());
final VersionAttributeView v2 = ioService.getFileAttributeView(f2,
VersionAttributeView.class);
assertNotNull(v2);
assertEquals(3,
v2.readAttributes().history().records().size());
final VersionAttributeView v3 = ioService.getFileAttributeView(f3,
VersionAttributeView.class);
assertNotNull(v3);
assertEquals(2,
v3.readAttributes().history().records().size());
}
}
@Test
public void batchTest() throws IOException, InterruptedException {
final Path init = ioService.get(URI.create("git://amend-repo-test/readme.txt"));
ioService.write(init,
"init!",
new CommentedOption("User Tester",
"message1"));
ioService.startBatch(new FileSystem[]{fs1});
assertTrue(fs1Batch.isOnBatch());
ioService.endBatch();
assertFalse(fs1Batch.isOnBatch());
}
@Test
public void justOneFSOnBatchTest() throws IOException, InterruptedException {
Path init = ioService.get(URI.create("git://amend-repo-test/readme.txt"));
ioService.write(init,
"init!",
new CommentedOption("User Tester",
"message1"));
init = ioService.get(URI.create("git://check-amend-repo-test/readme.txt"));
ioService.write(init,
"init!",
new CommentedOption("User Tester",
"message1"));
ioService.startBatch(new FileSystem[]{fs1});
assertTrue(fs1Batch.isOnBatch());
assertFalse(fs2Batch.isOnBatch());
ioService.endBatch();
assertFalse(fs1Batch.isOnBatch());
assertFalse(fs2Batch.isOnBatch());
}
@Test
public void testInnerBatch() throws IOException, InterruptedException {
Path init = ioService.get(URI.create("git://amend-repo-test/readme.txt"));
ioService.write(init,
"init!",
new CommentedOption("User Tester",
"message1"));
init = ioService.get(URI.create("git://check-amend-repo-test/readme.txt"));
ioService.write(init,
"init!",
new CommentedOption("User Tester",
"message1"));
ioService.startBatch(new FileSystem[]{fs1});
assertTrue(fs1Batch.isOnBatch());
ioService.startBatch(new FileSystem[]{fs1});
assertTrue(fs1Batch.isOnBatch());
ioService.endBatch();
assertTrue(fs1Batch.isOnBatch());
ioService.endBatch();
assertFalse(fs1Batch.isOnBatch());
}
@Test
public void assertNumberOfCommitsOnInnerBatch() throws IOException, InterruptedException {
final Path f11 = ioService.get(URI.create("git://check-amend-repo-test/f11.txt"));
// XXX: Workaround for UF-70: amend-test-repo has to contain something so it can receive the BATCH
ioService.write(f11,
"init f1!");
// END workaround
ioService.startBatch(new FileSystem[]{f11.getFileSystem()});
ioService.write(f11,
"f1-u1!");
ioService.endBatch();
VersionAttributeView v = ioService.getFileAttributeView(f11,
VersionAttributeView.class);
assertNotNull(v);
assertEquals(2,
v.readAttributes().history().records().size());
ioService.startBatch(new FileSystem[]{f11.getFileSystem()});
ioService.write(f11,
"f2-u2!");
//inner batch (samme commit)
ioService.startBatch(new FileSystem[]{f11.getFileSystem()});
ioService.write(f11,
"f2-u2 - inner batch!");
ioService.write(f11,
"f2-u2 - inner 2 batch!");
ioService.endBatch();
ioService.write(f11,
"f2-u2 - inner batch! last");
ioService.endBatch();
assertEquals("f2-u2 - inner batch! last",
ioService.readAllString(f11));
v = ioService.getFileAttributeView(f11,
VersionAttributeView.class);
assertNotNull(v);
assertEquals(4,
v.readAttributes().history().records().size());
}
@Test
public void testTwoStartedFsOnBatchByTheSameThread() throws IOException, InterruptedException {
Path init = ioService.get(URI.create("git://amend-repo-test/readme.txt"));
ioService.write(init,
"init!",
new CommentedOption("User Tester",
"message1"));
init = ioService.get(URI.create("git://check-amend-repo-test/readme.txt"));
ioService.write(init,
"init!",
new CommentedOption("User Tester",
"message1"));
ioService.startBatch(new FileSystem[]{fs1});
try {
ioService.startBatch(new FileSystem[]{fs1});
} catch (final Exception e) {
fail();
}
ioService.endBatch();
ioService.endBatch();
try {
ioService.endBatch();
fail();
} catch (final Exception e) {
}
}
@Test
public void testTwoFsOnBatchByTheSameThread() throws IOException, InterruptedException {
Path init = ioService.get(URI.create("git://amend-repo-test/readme.txt"));
ioService.write(init,
"init!",
new CommentedOption("User Tester",
"message1"));
init = ioService.get(URI.create("git://check-amend-repo-test/readme.txt"));
ioService.write(init,
"init!",
new CommentedOption("User Tester",
"message1"));
ioService.startBatch(new FileSystem[]{fs1});
assertTrue(fs1Batch.isOnBatch());
ioService.endBatch();
ioService.startBatch(new FileSystem[]{fs2});
assertTrue(fs2Batch.isOnBatch());
ioService.endBatch();
}
@Test
public void iCanLockMultipleFS() throws IOException, InterruptedException {
Path init = ioService.get(URI.create("git://amend-repo-test/readme.txt"));
ioService.write(init,
"init!",
new CommentedOption("User Tester",
"message1"));
init = ioService.get(URI.create("git://check-amend-repo-test/readme.txt"));
ioService.write(init,
"init!",
new CommentedOption("User Tester",
"message1"));
ioService.startBatch(new FileSystem[]{fs1, fs2});
assertTrue(fs1Batch.isOnBatch());
assertTrue(fs2Batch.isOnBatch());
ioService.endBatch();
assertFalse(fs1Batch.isOnBatch());
assertFalse(fs2Batch.isOnBatch());
}
@Test
public void testDifferentThreads() throws IOException, InterruptedException {
final Path init = ioService.get(URI.create("git://amend-repo-test/readme.txt"));
ioService.write(init,
"init!");
ioService.startBatch(new FileSystem[]{fs1});
System.out.println("After start batch");
new Thread("second") {
@Override
public void run() {
try {
System.out.println("Inner starting");
ioService.startBatch(new FileSystem[]{fs1});
System.out.println("Inner after batch");
final OutputStream innerOut = ioService.newOutputStream(init);
for (int i = 0; i < 100; i++) {
innerOut.write(("sss" + i).getBytes());
}
System.out.println("Inner after write");
innerOut.close();
System.out.println("Inner after close");
ioService.endBatch();
System.out.println("Inner after end batch");
} catch (Exception ex) {
ex.printStackTrace();
}
}
}.start();
System.out.println("After start 2nd Thread");
for (int i = 0; i < 100; i++) {
if (i % 20 == 0) {
Thread.sleep(10);
}
ioService.write(init,
("sss" + i).getBytes());
}
System.out.println("After writes");
ioService.endBatch();
System.out.println("After end batch");
}
@Test
public void testDifferentThreadsWithoutBatch() throws IOException, InterruptedException {
final Path init = ioService.get(URI.create("git://amend-repo-test/readme.txt"));
ioService.write(init,
"init!");
new Thread("second") {
@Override
public void run() {
try {
System.out.println("Inner starting");
final OutputStream innerOut = ioService.newOutputStream(init);
for (int i = 0; i < 100; i++) {
innerOut.write(("sss" + i).getBytes());
}
System.out.println("Inner after write");
innerOut.close();
} catch (Exception ex) {
ex.printStackTrace();
}
}
}.start();
System.out.println("After start 2nd Thread");
for (int i = 0; i < 100; i++) {
if (i % 20 == 0) {
Thread.sleep(10);
}
ioService.write(init,
("sss" + i).getBytes());
}
System.out.println("After writes");
}
@Test
public void testDifferentThreads3() throws IOException, InterruptedException {
final Path init = ioService.get(URI.create("git://amend-repo-test/readme.txt"));
ioService.write(init,
"init!");
ioService.startBatch(new FileSystem[]{fs1});
System.out.println("After start batch");
final Runnable runnable = new Runnable() {
@Override
public void run() {
try {
System.out.println("Inner starting");
ioService.startBatch(new FileSystem[]{fs1});
System.out.println("Inner after batch");
final OutputStream innerOut = ioService.newOutputStream(init);
for (int i = 0; i < 100; i++) {
innerOut.write(("sss" + i).getBytes());
}
System.out.println("Inner after write");
innerOut.close();
System.out.println("Inner after close");
ioService.endBatch();
System.out.println("Inner after end batch");
} catch (Exception ex) {
ex.printStackTrace();
}
}
};
final Thread thread = new Thread(runnable,
"second");
final Thread thread2 = new Thread(runnable,
"third");
thread.start();
Thread.sleep(100);
thread2.start();
Thread.sleep(100);
System.out.println("After start 2nd Thread");
for (int i = 0; i < 100; i++) {
if (i % 20 == 0) {
Thread.sleep(10);
}
ioService.write(init,
("sss" + i).getBytes());
}
System.out.println("After writes");
ioService.endBatch();
System.out.println("After end batch");
}
@Test
public void testDifferentThreadsNotBatchInners() throws IOException, InterruptedException {
final Path init = ioService.get(URI.create("git://amend-repo-test/readme.txt"));
ioService.write(init,
"init!");
ioService.startBatch(new FileSystem[]{fs1});
System.out.println("After start batch");
final Runnable runnable = new Runnable() {
@Override
public void run() {
try {
System.out.println("Inner starting");
final OutputStream innerOut = ioService.newOutputStream(init);
for (int i = 0; i < 100; i++) {
innerOut.write(("sss" + i).getBytes());
}
System.out.println("Inner after write");
innerOut.close();
System.out.println("Inner after end batch");
} catch (Exception ex) {
ex.printStackTrace();
}
}
};
final Thread thread = new Thread(runnable,
"second");
final Thread thread2 = new Thread(runnable,
"third");
thread.start();
Thread.sleep(100);
thread2.start();
Thread.sleep(100);
System.out.println("After start 2nd Thread");
for (int i = 0; i < 100; i++) {
if (i % 20 == 0) {
Thread.sleep(10);
}
ioService.write(init,
("sss" + i).getBytes());
}
System.out.println("After writes");
ioService.endBatch();
System.out.println("After end batch");
}
@Test
public void testDifferentThreadsNotBatchOuter() throws IOException, InterruptedException {
final Path init = ioService.get(URI.create("git://amend-repo-test/readme.txt"));
ioService.write(init,
"init!");
final Runnable runnable = new Runnable() {
@Override
public void run() {
try {
System.out.println("Inner starting");
ioService.startBatch(new FileSystem[]{fs1});
System.out.println("Inner after batch");
final OutputStream innerOut = ioService.newOutputStream(init);
for (int i = 0; i < 100; i++) {
ioService.write(init,
("sss" + i).getBytes());
}
System.out.println("Inner after write");
innerOut.close();
System.out.println("Inner after close");
ioService.endBatch();
System.out.println("Inner after end batch");
} catch (Exception ex) {
ex.printStackTrace();
}
}
};
final Thread thread = new Thread(runnable,
"second");
final Thread thread2 = new Thread(runnable,
"third");
thread.start();
Thread.sleep(100);
thread2.start();
Thread.sleep(100);
System.out.println("After start 2nd Thread");
for (int i = 0; i < 100; i++) {
if (i % 20 == 0) {
Thread.sleep(10);
}
ioService.write(init,
("sss" + i).getBytes());
}
System.out.println("After writes");
}
@Test
public void exceptionOnCleanUpAndUnsetBatchModeOnFileSystemsShouldReleaseLock() throws IOException, InterruptedException {
IOServiceDotFileImpl ioServiceSpy = spy((IOServiceDotFileImpl) ioService);
Mockito.doThrow(new RuntimeException()).when(ioServiceSpy).unsetBatchModeOn(fs1Batch);
final Path init = ioService.get(URI.create("git://amend-repo-test/readme.txt"));
ioServiceSpy.write(init,
"init!",
new CommentedOption("User Tester",
"message1"));
ioServiceSpy.startBatch(new FileSystem[]{fs1});
assertTrue(ioServiceSpy.getLockControl().isLocked());
try {
ioServiceSpy.endBatch();
} catch (Exception e) {
}
assertFalse(ioServiceSpy.getLockControl().isLocked());
}
}