Skip to content

Commit

Permalink
Merge pull request #1307 from BladeRunnerJS/0.15.3-release
Browse files Browse the repository at this point in the history
0.15.3 release
  • Loading branch information
thanhc committed Mar 26, 2015
2 parents b31cf7f + 9c5a858 commit 3c3177a
Show file tree
Hide file tree
Showing 36 changed files with 1,030 additions and 73 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
package org.bladerunnerjs.api.memoization;

import org.bladerunnerjs.memoization.PollingFileModificationObserverThread;
import org.bladerunnerjs.model.App;
import org.bladerunnerjs.model.Aspect;
import org.bladerunnerjs.model.BRJS;
import org.bladerunnerjs.model.exception.ConfigException;
import org.bladerunnerjs.testing.specutility.engine.SpecTest;
import org.bladerunnerjs.memoization.WatchingFileModificationObserverThread;
import org.junit.After;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;


public class BundleCachingIntegrationTest extends SpecTest
{
private StringBuffer response = new StringBuffer();

@Before
public void initTestObjects() throws Exception
{
given(brjs).automaticallyFindsBundlerPlugins()
.and(brjs).automaticallyFindsMinifierPlugins()
.and(brjs).hasBeenCreated();

// dont use fields for BRJS objects since we recreate BRJS in each test
}

@SuppressWarnings("deprecation")
@After
public void stopServer() throws Exception {
if (brjs != null) {
brjs.applicationServer(appServerPort).stop();
}
try {
brjs.getFileWatcherThread().interrupt();
brjs.getFileWatcherThread().stop();
} catch (Exception ex) {
// ignore
}
}

@Test @Ignore //TODO: this test is unreliable - fix it
public void fileWatcherWatchesFolderBrjsAppsAtTheSameLevelAsSdk() throws Throwable {
given(brjs).hasBeenAuthenticallyCreatedWithFileWatcherThread();
App app = brjs.app("app1");
Aspect aspect = app.defaultAspect();
given(app).hasBeenCreated()
.and(aspect).hasBeenCreated()
.and(aspect).indexPageHasContent("require('appns/App')")
.and(aspect).classFileHasContent("App", "// App.js")
.and(aspect).hasReceivedRequest("js/dev/combined/bundle.js");
when(aspect).indexPageRefersToWithoutNotifyingFileRegistry("require('appns/AppClass')")
.and(aspect).fileHasContentsWithoutNotifyingFileRegistry("src/AppClass.js", "// AppClass.js");
then(aspect).devResponseEventuallyContains("js/dev/combined/bundle.js", "AppClass.js", response)
.and(response).doesNotContainText("App.js");
}

@Test @Ignore //TODO: this test is unreliable - fix it
public void fileWatcherPollsFolderBrjsAppsAtTheSameLevelAsSdk() throws Throwable {
given(brjs).hasBeenAuthenticallyCreatedWithFilePollingThread();
App app = brjs.app("app1");
Aspect aspect = app.defaultAspect();
given(app).hasBeenCreated()
.and(aspect).hasBeenCreated()
.and(aspect).indexPageHasContent("require('appns/App')")
.and(aspect).classFileHasContent("App", "// App.js")
.and(aspect).hasReceivedRequest("js/dev/combined/bundle.js");
when(aspect).indexPageRefersToWithoutNotifyingFileRegistry("require('appns/AppClass')")
.and(aspect).fileHasContentsWithoutNotifyingFileRegistry("src/AppClass.js", "// AppClass.js");
then(aspect).devResponseEventuallyContains("js/dev/combined/bundle.js", "AppClass.js", response)
.and(response).doesNotContainText("App.js");
}

@Test
public void brjsConfCanBeUsedToConfigureFileObserverToPolling() throws Throwable {
given(brjs.bladerunnerConf()).hasFileObserverValue("polling")
.and(logging).enabled();
when(brjs).hasBeenAuthenticallyCreatedWithAutoConfiguredObserverThread();
then(logging).debugMessageReceived(BRJS.Messages.FILE_WATCHER_MESSAGE, PollingFileModificationObserverThread.class.getSimpleName())
.and(logging).otherMessagesIgnored();

}

@Test
public void brjsConfCanBeUsedToConfigureFileObserverToPollingWithASetInterval() throws Throwable {
given(brjs.bladerunnerConf()).hasFileObserverValue("polling:1000")
.and(logging).enabled();
when(brjs).hasBeenAuthenticallyCreatedWithAutoConfiguredObserverThread();
then(logging).debugMessageReceived(BRJS.Messages.FILE_WATCHER_MESSAGE, PollingFileModificationObserverThread.class.getSimpleName())
.and(logging).debugMessageReceived(PollingFileModificationObserverThread.THREAD_INIT_MESSAGE, PollingFileModificationObserverThread.class.getSimpleName(), 1000)
.and(logging).otherMessagesIgnored();
}

@Test
public void brjsConfCanBeUsedToConfigureFileObserveToWatching() throws Throwable {
given(brjs.bladerunnerConf()).hasFileObserverValue("watching")
.and(logging).enabled();
when(brjs).hasBeenAuthenticallyCreatedWithAutoConfiguredObserverThread();
then(logging).debugMessageReceived(BRJS.Messages.FILE_WATCHER_MESSAGE, WatchingFileModificationObserverThread.class.getSimpleName())
.and(logging).otherMessagesIgnored();
}

@Test
public void watchingFileObserverIsUsedAsDefault() throws Throwable {
given(logging).enabled();
when(brjs).hasBeenAuthenticallyCreatedWithAutoConfiguredObserverThread();
then(logging).debugMessageReceived(BRJS.Messages.FILE_WATCHER_MESSAGE, WatchingFileModificationObserverThread.class.getSimpleName())
.and(logging).otherMessagesIgnored();
}

@Test @Ignore //TODO: this test is unreliable - fix it
public void brjsConfConfiguredFileObserverDetectsChanges() throws Throwable {
given(brjs).hasBeenAuthenticallyCreatedWithAutoConfiguredObserverThread();
App app = brjs.app("app1");
Aspect aspect = app.defaultAspect();
given(app).hasBeenCreated()
.and(aspect).hasBeenCreated()
.and(aspect).indexPageHasContent("require('appns/App')")
.and(aspect).classFileHasContent("App", "// App.js")
.and(aspect).hasReceivedRequest("js/dev/combined/bundle.js");
when(aspect).indexPageRefersToWithoutNotifyingFileRegistry("require('appns/AppClass')")
.and(aspect).fileHasContentsWithoutNotifyingFileRegistry("src/AppClass.js", "// AppClass.js");
then(aspect).devResponseEventuallyContains("js/dev/combined/bundle.js", "AppClass.js", response)
.and(response).doesNotContainText("App.js");
}

@Test
public void exceptionIsThrownIfFileObserverValueIsInvalid() throws Throwable {
given(brjs.bladerunnerConf()).hasFileObserverValue("invalid");
when(brjs).hasBeenAuthenticallyCreatedWithAutoConfiguredObserverThread();
then(exceptions).verifyException(ConfigException.class, "invalid", "polling(:([0-9]+))?", "watching");
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import java.util.Collections;
import java.util.List;

import org.bladerunnerjs.memoization.WatchingFileModificationObserverThread;
import org.bladerunnerjs.logging.Logger;
import org.bladerunnerjs.model.BRJS;
import org.bladerunnerjs.utility.FileUtils;
Expand All @@ -35,7 +36,7 @@ public class FileModificationWatcherThreadTest
private DefaultWatchKeyService mockWatchKeyService;
private FileModificationRegistry mockModificationRegistry;
private MemoizedFile rootWatchDir;
private FileModificationWatcherThread modificationWatcherThread;
private WatchingFileModificationObserverThread modificationWatcherThread;
private List<File> fileChanges = Collections.synchronizedList( new ArrayList<>() );
private File fileInRoot;
private File dirInRoot;
Expand Down Expand Up @@ -205,7 +206,7 @@ public void newNestedDirectoriesCauseWatchKeysToBeCreatedForTheNewDirectory() th

@Test // we use the package private methods on FileModificationWatcherThread here to avoid having a multithreaded test
public void usingTheRealWatchServiceDetectsFileChanges() throws Exception {
modificationWatcherThread = new FileModificationWatcherThread(mockBrjs, new WatchKeyServiceFactory());
modificationWatcherThread = new WatchingFileModificationObserverThread(mockBrjs, new WatchKeyServiceFactory());

modificationWatcherThread.init();

Expand All @@ -218,7 +219,7 @@ public void usingTheRealWatchServiceDetectsFileChanges() throws Exception {

@Test // we use the package private methods on FileModificationWatcherThread here to avoid having a multithreaded test
public void usingTheRealWatchServiceDetectsFileNestedChanges() throws Exception {
modificationWatcherThread = new FileModificationWatcherThread(mockBrjs, new WatchKeyServiceFactory());
modificationWatcherThread = new WatchingFileModificationObserverThread(mockBrjs, new WatchKeyServiceFactory());

modificationWatcherThread.init();

Expand Down Expand Up @@ -261,7 +262,7 @@ private boolean waitForUpdate(File expectedFile, boolean mustBeIndex0) throws In

private void createAndInitWatcher() throws IOException
{
modificationWatcherThread = new FileModificationWatcherThread(mockBrjs, mockWatchServiceFactory);
modificationWatcherThread = new WatchingFileModificationObserverThread(mockBrjs, mockWatchServiceFactory);
modificationWatcherThread.init();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import static org.bladerunnerjs.appserver.BRJSApplicationServer.Messages.*;
import static org.bladerunnerjs.appserver.ApplicationServerUtils.Messages.*;

import java.io.File;
import java.io.IOException;
import java.net.ServerSocket;

Expand All @@ -11,6 +12,7 @@
import org.bladerunnerjs.appserver.ApplicationServer;
import org.bladerunnerjs.appserver.BRJSApplicationServer;
import org.bladerunnerjs.model.App;
import org.bladerunnerjs.model.Aspect;
import org.bladerunnerjs.model.BRJS;
import org.bladerunnerjs.model.DirNode;
import org.bladerunnerjs.model.TemplateGroup;
Expand All @@ -35,11 +37,16 @@ public class AppServerTest extends SpecTest
DirNode appJars;
ServerSocket socket;
Servlet helloWorldServlet;
TemplateGroup templates;
TemplateGroup templates;
Aspect aspect;
StringBuffer response = new StringBuffer();

File secondaryTempFolder;

@Before
public void initTestObjects() throws Exception {
given(brjs).automaticallyFindsBundlerPlugins()
.and(brjs).automaticallyFindsMinifierPlugins()
.and(brjs).hasModelObserverPlugins(new AppDeploymentObserverPlugin())
.and(brjs).hasContentPlugins(new MockContentPlugin())
.and(brjs).hasBeenCreated()
Expand All @@ -51,6 +58,7 @@ public void initTestObjects() throws Exception {
appServer = brjs.applicationServer(appServerPort);
app1 = brjs.app("app1");
app2 = brjs.app("app2");
aspect = app1.defaultAspect();
templates = brjs.sdkTemplateGroup("default");
sysapp1 = brjs.systemApp("sysapp1");
sysapp2 = brjs.systemApp("sysapp2");
Expand All @@ -67,6 +75,7 @@ public void stopServer() throws Exception
given(brjs.applicationServer(appServerPort)).stopped()
.and(brjs.applicationServer(appServerPort)).requestTimesOutFor("/");
if (socket != null && socket.isBound()) { socket.close(); }
if (secondaryTempFolder != null) org.apache.commons.io.FileUtils.deleteQuietly(secondaryTempFolder);
}

@Test
Expand Down Expand Up @@ -209,29 +218,32 @@ public void otherServletsCanBeAddedWithExtensionMapping() throws Exception
}

@Test
public void newAppsAreAutomaticallyHostedWhenRunningCreateAppCommandFromADifferentModelInstance() throws Exception
public void newAppsAreAutomaticallyHostedWhenRunningCreateAppCommandFromADifferentModelInstanceAndOnlyAppsDirectoryExists() throws Exception
{
given(brjs).hasBeenAuthenticallyCreatedWithFileWatcherThread()
.and(templates).templateGroupCreated()
.and(templates.template("app")).containsFile("fileForApp.txt")
given(brjs).doesNotContainFolder("brjs-apps")
.and(brjs).containsFolder("apps")
.and(brjs).hasBeenAuthenticallyCreatedWithFileWatcherThread();
/*and*/ secondBrjsProcess.close(); secondBrjsProcess = createNonTestModel();
given(brjs.sdkTemplateGroup("default")).templateGroupCreated()
.and(brjs.sdkTemplateGroup("default").template("app")).containsFile("index.html")
.and(brjs.applicationServer(appServerPort)).started();
when(secondBrjsProcess).runCommand("create-app", "app1", "blah");
then(appServer).requestCanEventuallyBeMadeFor("/app1/");
}

@Test
public void newAppsAreHostedOnAppserverAfterServerRestartWhenCreateAppCommandUsedFromADifferentModelInstance() throws Exception
public void newAppsAreAutomaticallyHostedWhenRunningCreateAppCommandFromADifferentModelInstanceAndWorkingDirIsSeperateFromSdk() throws Exception
{
given(brjs).hasBeenAuthenticallyCreatedWithFileWatcherThread()
.and(templates).templateGroupCreated()
.and(templates.template("app")).containsFile("fileForApp.txt")
secondaryTempFolder = org.bladerunnerjs.utility.FileUtils.createTemporaryDirectory(this.getClass());
given(brjs).hasBeenAuthenticallyCreatedWithWorkingDir(secondaryTempFolder);
/*and*/ secondBrjsProcess = createNonTestModel(secondaryTempFolder);
given(brjs.sdkTemplateGroup("default").template("app")).containsFile("index.html")
.and(brjs.applicationServer(appServerPort)).started();
when(secondBrjsProcess).runCommand("create-app", "app1", "blah")
.and(brjs.applicationServer(appServerPort)).stopped()
.and(brjs.applicationServer(appServerPort)).started();
then(appServer).requestCanEventuallyBeMadeFor("/app1/");
when(secondBrjsProcess).runCommand("create-app", "app1", "blah");
then(brjs.applicationServer(appServerPort)).requestCanEventuallyBeMadeFor("/app1/");
}


@Test
public void newAppsAreHostedViaADifferentModelOnAppserverAfterServerRestart() throws Exception
{
Expand Down Expand Up @@ -284,4 +296,5 @@ public void errorCode404IsThrownIfResourceIsNotFound() throws Exception {
given(appServer).started();
then(appServer).requestForUrlContains("/app1/v/dev/no-such-content-plugin", "Error 404");
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import org.bladerunnerjs.model.App;
import org.bladerunnerjs.model.Blade;

import org.bladerunnerjs.model.NamedDirNode;
import org.bladerunnerjs.model.TestPack;
import org.bladerunnerjs.model.events.CommandExecutedEvent;
Expand Down Expand Up @@ -29,7 +30,7 @@ public void initTestObjects() throws Exception
public void theBrjsConfIsWrittenOnPopulate() throws Exception {
given(brjsTemplate).hasBeenCreated();
when(brjs).populate();
then(brjs).fileHasContents("conf/brjs.conf", "defaultFileCharacterEncoding: UTF-8\nignoredPaths: .svn, .git\njettyPort: 7070\nloginRealm: BladeRunnerLoginRealm");
then(brjs).fileHasContents("conf/brjs.conf", "defaultFileCharacterEncoding: UTF-8\nfileObserver: watching\nignoredPaths: .svn, .git\njettyPort: 7070\nloginRealm: BladeRunnerLoginRealm");
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ public void initTestObjects() throws Exception
@Test
public void bladerunnerConfWillHaveSensibleDefaultsIfItDoesntAlreadyExist() throws Exception {
when(brjs).bladerunnerConf().write();
then(brjs).fileHasContents("conf/brjs.conf", "defaultFileCharacterEncoding: UTF-8\nignoredPaths: .svn, .git\njettyPort: 7070\nloginRealm: BladeRunnerLoginRealm");
then(brjs).fileHasContents("conf/brjs.conf", "defaultFileCharacterEncoding: UTF-8\nfileObserver: watching\nignoredPaths: .svn, .git\njettyPort: 7070\nloginRealm: BladeRunnerLoginRealm");
}

@Test
Expand All @@ -30,7 +30,7 @@ public void readingBladerunnerConfWithMissingLoginReamlUsesTheDefault() throws E
public void bladerunnerConfThatAlreadyExistsCanBeReadAndModified() throws Exception {
given(brjs).containsFileWithContents("conf/brjs.conf", "defaultFileCharacterEncoding: UTF-8\njettyPort: 7070\nloginRealm: BladeRunnerLoginRealm");
when(brjs).bladerunnerConf().setJettyPort(8888).setDefaultFileCharacterEncoding("ISO-8859-1").write();
then(brjs).fileHasContents("conf/brjs.conf", "defaultFileCharacterEncoding: ISO-8859-1\nignoredPaths: .svn, .git\njettyPort: 8888\nloginRealm: BladeRunnerLoginRealm");
then(brjs).fileHasContents("conf/brjs.conf", "defaultFileCharacterEncoding: ISO-8859-1\nfileObserver: watching\nignoredPaths: .svn, .git\njettyPort: 8888\nloginRealm: BladeRunnerLoginRealm");
}

@Test
Expand Down Expand Up @@ -84,7 +84,7 @@ public void readingAnBladerunnerConfFileWithEmptyValuesWillCauseAnException() th
}

@Test
public void invalidPropertyInBladerunnerConfCausesAnExcpetion() throws Exception {
public void invalidPropertyInBladerunnerConfCausesAnException() throws Exception {
given(brjs).containsFileWithContents("conf/brjs.conf", "sillyProperty: UTF-8\nloginRealm: BladeRunnerLoginRealm");
when(brjs).bladerunnerConf();
then(exceptions).verifyException(ConfigException.class, brjs.file("conf/brjs.conf").getPath(), unquoted("Unable to find property 'sillyProperty'"));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,6 @@ public void jsStyleChangesAreProperlyDetectedIfTheFileChangesDirectlyOnDisk() th
.and(initialResponse).containsText("lib.Lib =")
.and(secondResponse).doesNotContainText("mergePackageBlock")
.and(secondResponse).doesNotContainText("lib.Lib = require(");
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,9 @@ public Map<WatchKey,Path> createWatchKeysForDir(Path dirPath, boolean isNewlyDis
File dir = dirPath.toFile();
Collection<File> subDirs = FileUtils.listFilesAndDirs(dir, FalseFileFilter.INSTANCE, TrueFileFilter.INSTANCE);
for (File subDir : subDirs) {
watchKeys.put(createWatchKeyForDir(subDir.toPath()), subDir.toPath());
if (subDir.isDirectory()) {
watchKeys.put(createWatchKeyForDir(subDir.toPath()), subDir.toPath());
}
}

return watchKeys;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,20 +50,20 @@ public void incrementChildFileVersions(File file) {
Set<String> lastModifiedMapKeySet = new HashSet<>( lastModifiedMap.keySet() ); // copy the set to prevent concurrent modified exceptions
for (String path : lastModifiedMapKeySet) {
if (path.startsWith(filePath)) {
lastModifiedMap.get(path).incrememntValue();
lastModifiedMap.get(path).incrementValue();
}
}
}

public void incrementAllFileVersions() {
for (FileVersion version : lastModifiedMap.values()) {
version.incrememntValue();
version.incrementValue();
}
}

private void incrementFileAndParentVersion(File file) {
while (file != null && !file.equals(rootFile)) {
getOrCreateVersionValue(file).incrememntValue();
getOrCreateVersionValue(file).incrementValue();
file = file.getParentFile();
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ public class FileModifiedChecker
{
private FileModificationRegistry fileModificationRegistry;
private File file;
private long lastModifiedTime = -1;
private long lastFileVersion = -1;
private FileVersion fileVersion;

public FileModifiedChecker(FileModificationRegistry fileModificationRegistry, RootNode rootNode, File file) {
Expand All @@ -21,10 +21,9 @@ public boolean hasChangedSinceLastCheck() {
if (fileVersion == null) {
fileVersion = fileModificationRegistry.getFileVersionObject(file);
}
long newLastModified = fileVersion.getValue();

boolean hasChangedSinceLastCheck = (newLastModified > lastModifiedTime);
lastModifiedTime = newLastModified;
long newFileVersion = fileVersion.getValue();
boolean hasChangedSinceLastCheck = (newFileVersion > lastFileVersion);
lastFileVersion = newFileVersion;

return hasChangedSinceLastCheck;
}
Expand Down
Loading

0 comments on commit 3c3177a

Please sign in to comment.