Skip to content

Commit 612945c

Browse files
committed
For #1529: configurations and automated tests
- replication implementation - distributable WAR - listener - configuration property - bootstrap caches upon web app start - PE check - configuration for replication setup - Orbeon Forms properties and logging - Ehcache - HAProxy - Tomcat - tests - pull Docker images - use newer version of Docker and don't start default docker service - ability to start/stop Docker instances from integration tests - make `orbeon-war` a cross-project - add first integration tests - misc - some utilities for Future - some Node.js facades - upgrade Scala.js to 0.6.19
1 parent f199f38 commit 612945c

File tree

25 files changed

+1449
-67
lines changed

25 files changed

+1449
-67
lines changed

.travis.yml

+8
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,11 @@ before_cache:
4040
# Tricks to avoid unnecessary cache updates
4141
- find $HOME/.ivy2 -name "ivydata-*.properties" -delete
4242
- find $HOME/.sbt -name "*.lock" -delete
43+
before_install:
44+
- curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
45+
- sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"
46+
- sudo apt-get update
47+
- sudo apt-get -y install docker-ce
4348
install:
4449
# From https://docs.travis-ci.com/user/languages/java/: "Because there is no single standard way of installing project dependencies with Ant, you need to
4550
# specify the exact command to run using install". Here we install npm dependencies for Node.js as we need them for integration tests.
@@ -51,5 +56,8 @@ before_script:
5156
- mysql --protocol=TCP --host=localhost --user root -e "GRANT ALL PRIVILEGES ON *.* TO 'orbeon'@'localhost' WITH GRANT OPTION"
5257
- createuser --superuser orbeon
5358
- createdb --owner=orbeon orbeon
59+
# Download other Docker images
60+
- if [ "$TARGET" == "test-unit" ]; then docker pull tomcat:8.0; fi
61+
- if [ "$TARGET" == "test-unit" ]; then docker pull haproxy:1.7; fi
5462
script:
5563
- "ant $TARGET"

build.sbt

+63-11
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import sbt.Keys._
2+
import org.orbeon.sbt.OrbeonSupport
23
import org.orbeon.sbt.OrbeonSupport._
34
import org.orbeon.sbt.OrbeonWebappPlugin
5+
import org.scalajs.sbtplugin.ScalaJSPlugin.AutoImport.jsEnv
46
//import sbtcross.{crossProject, CrossType} // until Scala.js 1.0.0 is released
57

68
val DefaultOrbeonFormsVersion = "2016.3-SNAPSHOT"
@@ -147,7 +149,7 @@ val JarFilesToExcludeFromLiferayWar = Set(
147149

148150
val TestResourceManagerPaths = List(
149151
"src/test/resources", // so that Java processor tests work
150-
"orbeon-war/src/main/webapp/WEB-INF/resources"
152+
"orbeon-war/jvm/src/main/webapp/WEB-INF/resources"
151153
)
152154

153155
def resourceManagerProperties(buildBaseDirectory: File): List[String] = {
@@ -246,7 +248,7 @@ lazy val unmanagedJarsSettings = Seq(
246248

247249
lazy val commonSettings = Seq(
248250

249-
jsEnv := JSDOMNodeJSEnv().value,
251+
jsEnv := new org.scalajs.jsenv.jsdomnodejs.JSDOMNodeJSEnv(),
250252

251253
javacOptions ++= Seq(
252254
"-encoding", "utf8",
@@ -340,6 +342,7 @@ lazy val common = (crossProject.crossType(CrossType.Full) in file("common"))
340342
)
341343
)
342344
.jsSettings(
345+
libraryDependencies += "org.scala-lang.modules" %% "scala-async" % "0.9.7" % "provided"
343346
)
344347

345348
lazy val commonJVM = common.jvm
@@ -492,7 +495,7 @@ lazy val formBuilderJVM = formBuilder.jvm
492495
lazy val formBuilderJS: Project = formBuilder.js
493496
.dependsOn(
494497
commonJS,
495-
xformsJS % "test->test;compile->compile",
498+
xformsJS % "test->test;compile->compile",
496499
formRunnerJS
497500
)
498501
.settings(
@@ -507,11 +510,8 @@ lazy val formBuilderJS: Project = formBuilder.js
507510

508511
jsDependencies in Test += ProvidedJS / "ops/javascript/orbeon/util/jquery-orbeon.js" dependsOn "jquery.js",
509512

510-
scalaJSUseMainModuleInitializer in Compile := true,
511-
scalaJSUseMainModuleInitializer in Test := false,
512-
513-
testOptions in Test += Tests.Setup(() println("Setup")),
514-
testOptions in Test += Tests.Cleanup(() println("Cleanup")),
513+
scalaJSUseMainModuleInitializer in Compile := false,
514+
scalaJSUseMainModuleInitializer in Test := false,
515515

516516
fastOptJSToLocalResources := copyScalaJSToExplodedWar(
517517
(fastOptJS in Compile).value.data,
@@ -589,6 +589,19 @@ lazy val xformsJS: Project = xforms.js
589589
)
590590
)
591591

592+
lazy val nodeFacades = (project in file("node-facades"))
593+
.enablePlugins(ScalaJSPlugin)
594+
.settings(commonSettings: _*)
595+
.settings(
596+
name := "orbeon-node-facades",
597+
598+
parallelExecution in Test := false,
599+
scalaJSUseMainModuleInitializer in Test := false,
600+
jsEnv in Test := new org.scalajs.jsenv.nodejs.NodeJSEnv(),
601+
602+
scalaJSLinkerConfig ~= { _.withModuleKind(ModuleKind.CommonJSModule) }
603+
)
604+
592605
lazy val core = (project in file("src"))
593606
.enablePlugins(BuildInfoPlugin, SbtCoffeeScript, SbtWeb)
594607
.dependsOn(commonJVM, dom, xupdate)
@@ -615,10 +628,13 @@ lazy val core = (project in file("src"))
615628
libraryDependencies ++= CoreLibraryDependencies
616629
)
617630

618-
lazy val orbeonWar = (project in file("orbeon-war"))
631+
lazy val orbeonWar = (crossProject.crossType(CrossType.Dummy) in file("orbeon-war"))
619632
.settings(
620-
name := "orbeon-war"
633+
name := "orbeon-war",
634+
exportJars := false
621635
)
636+
637+
lazy val orbeonWarJVM = orbeonWar.jvm
622638
.dependsOn(
623639
commonJVM,
624640
dom,
@@ -635,6 +651,41 @@ lazy val orbeonWar = (project in file("orbeon-war"))
635651
.settings(OrbeonWebappPlugin.projectSettings: _*)
636652
.settings(commonSettings: _*)
637653

654+
655+
lazy val orbeonWarJS = orbeonWar.js
656+
.enablePlugins(BuildInfoPlugin)
657+
.settings(commonSettings: _*)
658+
.dependsOn(
659+
commonJS,
660+
xformsJS,
661+
nodeFacades
662+
)
663+
.settings(
664+
665+
// Poor man's way to pass parameters to the test suite
666+
buildInfoPackage := "org.orbeon.fr",
667+
buildInfoObject := "TestParametersFromSbt",
668+
buildInfoKeys := Seq[BuildInfoKey](
669+
"baseDirectory" (baseDirectory in ThisBuild).value.getAbsolutePath
670+
),
671+
672+
libraryDependencies ++= Seq(
673+
"org.scala-js" %%% "scalajs-dom" % ScalaJsDomVersion,
674+
"be.doeraene" %%% "scalajs-jquery" % ScalaJsJQueryVersion,
675+
"fr.hmil" %%% "roshttp" % "2.0.2" % Test,
676+
"org.scala-lang.modules" %% "scala-async" % "0.9.7" % "provided"
677+
),
678+
679+
parallelExecution in Test := false,
680+
scalaJSUseMainModuleInitializer in Test := false,
681+
jsEnv in Test := new org.scalajs.jsenv.nodejs.NodeJSEnv(),
682+
scalaJSLinkerConfig ~= { _.withModuleKind(ModuleKind.CommonJSModule) },
683+
684+
testOptions in Test +=
685+
Tests.Setup(() OrbeonSupport.dummyDependency((Keys.`package` in orbeonWarJVM).value))
686+
)
687+
688+
638689
lazy val root = (project in file("."))
639690
.aggregate(
640691
commonJVM,
@@ -652,7 +703,8 @@ lazy val root = (project in file("."))
652703
portletSupport,
653704
formRunnerProxyPortlet,
654705
fullPortlet,
655-
orbeonWar
706+
orbeonWarJVM,
707+
orbeonWarJS
656708
)
657709
.settings(
658710
// TEMP: override so that root project doesn't search under src

build.xml

+11-11
Original file line numberDiff line numberDiff line change
@@ -157,12 +157,12 @@
157157
-ignorewarnings
158158
-forceprocessing
159159

160-
-injars orbeon-war/target/webapp/WEB-INF/lib/(!slf4j-api-1.7.21.jar,**.jar;)
160+
-injars orbeon-war/jvm/target/webapp/WEB-INF/lib/(!slf4j-api-1.7.21.jar,**.jar;)
161161
-outjars ${temp.jar}(**.class,!**)
162162

163163
-libraryjars ${java.home}/lib/rt.jar
164164

165-
-libraryjars orbeon-war/target/webapp/WEB-INF/lib/slf4j-api-1.7.21.jar
165+
-libraryjars orbeon-war/jvm/target/webapp/WEB-INF/lib/slf4j-api-1.7.21.jar
166166

167167
-libraryjars lib/provided/javax.servlet-api-3.0.1.jar
168168
-libraryjars lib/provided/portlet-api_2.0.jar
@@ -206,12 +206,12 @@
206206
-ignorewarnings
207207
-forceprocessing
208208

209-
-injars orbeon-war/target/webapp/WEB-INF/lib/(!slf4j-api-1.7.21.jar,**.jar;)
209+
-injars orbeon-war/jvm/target/webapp/WEB-INF/lib/(!slf4j-api-1.7.21.jar,**.jar;)
210210
-outjars ${temp.jar}(**.class,!**)
211211

212212
-libraryjars ${java.home}/lib/rt.jar
213213

214-
-libraryjars orbeon-war/target/webapp/WEB-INF/lib/slf4j-api-1.7.21.jar
214+
-libraryjars orbeon-war/jvm/target/webapp/WEB-INF/lib/slf4j-api-1.7.21.jar
215215

216216
-libraryjars lib/provided/javax.servlet-api-3.0.1.jar
217217
-libraryjars lib/provided/portlet-api_2.0.jar
@@ -257,12 +257,12 @@
257257
-ignorewarnings
258258
-forceprocessing
259259

260-
-injars orbeon-war/target/webapp/WEB-INF/lib/(!slf4j-api-1.7.21.jar,**.jar;)
260+
-injars orbeon-war/jvm/target/webapp/WEB-INF/lib/(!slf4j-api-1.7.21.jar,**.jar;)
261261
-outjars ${temp.jar}(**.class,!**)
262262

263263
-libraryjars ${java.home}/lib/rt.jar
264264

265-
-libraryjars orbeon-war/target/webapp/WEB-INF/lib/slf4j-api-1.7.21.jar
265+
-libraryjars orbeon-war/jvm/target/webapp/WEB-INF/lib/slf4j-api-1.7.21.jar
266266

267267
-libraryjars lib/provided/javax.servlet-api-3.0.1.jar
268268
-libraryjars lib/provided/portlet-api_2.0.jar
@@ -295,8 +295,8 @@
295295
</exec>
296296

297297
<!-- Make sure we remove PathMap from Saxon as we have our own implementation -->
298-
<delete file="orbeon-war/target/webapp/WEB-INF/lib/${saxon.jar}"/>
299-
<jar destfile="orbeon-war/target/webapp/WEB-INF/lib/${saxon.jar}">
298+
<delete file="orbeon-war/jvm/target/webapp/WEB-INF/lib/${saxon.jar}"/>
299+
<jar destfile="orbeon-war/jvm/target/webapp/WEB-INF/lib/${saxon.jar}">
300300
<zipfileset src="lib/runtime/${saxon.jar}" excludes="org/orbeon/saxon/expr/PathMap*.class"/>
301301
</jar>
302302

@@ -327,7 +327,7 @@
327327

328328
<target name="orbeon-dev-war" depends="war-common" description="Create exploded WAR">
329329
<copy todir="build/orbeon-war">
330-
<fileset dir="orbeon-war/target/webapp">
330+
<fileset dir="orbeon-war/jvm/target/webapp">
331331
<!-- Filter local eXist that that might (but shouldn't) be in there -->
332332
<exclude name="WEB-INF/exist-data/**"/>
333333
</fileset>
@@ -339,7 +339,7 @@
339339
<mkdir dir="build/distrib"/>
340340

341341
<zip zipfile="build/distrib/${versioned-name}.war">
342-
<zipfileset dir="orbeon-war/target/webapp">
342+
<zipfileset dir="orbeon-war/jvm/target/webapp">
343343
<!-- Filter local eXist that that might (but shouldn't) be in there -->
344344
<exclude name="WEB-INF/exist-data/**"/>
345345
</zipfileset>
@@ -723,7 +723,7 @@
723723
<!-- http://exist-db.org/ant-tasks.html -->
724724
<typedef resource="org/exist/ant/antlib.xml" uri="http://exist-db.org/ant">
725725
<classpath>
726-
<fileset dir="orbeon-war/target/webapp/WEB-INF/lib">
726+
<fileset dir="orbeon-war/jvm/target/webapp/WEB-INF/lib">
727727
<include name="**/*.jar"/>
728728
</fileset>
729729
</classpath>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
/**
2+
* Copyright (C) 2017 Orbeon, Inc.
3+
*
4+
* This program is free software; you can redistribute it and/or modify it under the terms of the
5+
* GNU Lesser General Public License as published by the Free Software Foundation; either version
6+
* 2.1 of the License, or (at your option) any later version.
7+
*
8+
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
9+
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
10+
* See the GNU Lesser General Public License for more details.
11+
*
12+
* The full text of the license is available at http://www.gnu.org/copyleft/lesser.html
13+
*/
14+
package org.orbeon.oxf.util
15+
16+
import scala.concurrent.duration.FiniteDuration
17+
import scala.concurrent.{ExecutionContext, Future, Promise}
18+
import scala.scalajs.js.timers.setTimeout
19+
import scala.util.{Failure, Success, Try}
20+
import scala.async.Async._
21+
import scala.concurrent.duration._
22+
23+
object FutureUtils {
24+
25+
def delay(delay: FiniteDuration): Future[Unit] = {
26+
val p = Promise[Unit]()
27+
setTimeout(delay) {
28+
p.success(())
29+
}
30+
p.future
31+
}
32+
33+
def eventually[T](
34+
interval : FiniteDuration,
35+
timeout : FiniteDuration)(
36+
block : Future[T])(implicit
37+
execContext : ExecutionContext
38+
): Future[Try[T]] = async {
39+
40+
val startTime = System.currentTimeMillis
41+
42+
var result: Try[T] = null
43+
44+
var done = false
45+
while(! done) {
46+
await(block.toTry) match {
47+
case v @ Success(value)
48+
result = v
49+
done = true
50+
case v @ Failure(_)
51+
if ((System.currentTimeMillis - startTime).millis > timeout) {
52+
result = v
53+
done = true
54+
} else {
55+
await(delay(interval))
56+
}
57+
}
58+
}
59+
60+
result
61+
}
62+
63+
implicit class FutureOps[T](val f: Future[T]) extends AnyVal {
64+
def toTry(implicit executor: ExecutionContext): Future[Try[T]] =
65+
f map Success.apply recover PartialFunction(Failure.apply)
66+
}
67+
68+
}

0 commit comments

Comments
 (0)