/
CoreSpec.scala
238 lines (205 loc) · 8.18 KB
/
CoreSpec.scala
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
/*
* Copyright © 2021 - 2022 Swiss National Data and Service Center for the Humanities and/or DaSCH Service Platform contributors.
* SPDX-License-Identifier: Apache-2.0
*/
package org.knora.webapi
import akka.actor.ActorRef
import akka.actor.ActorSystem
import akka.actor.Props
import akka.event.LoggingAdapter
import akka.pattern.ask
import akka.stream.Materializer
import akka.testkit.ImplicitSender
import akka.testkit.TestKit
import akka.util.Timeout
import com.typesafe.config.Config
import com.typesafe.config.ConfigFactory
import org.knora.webapi.auth.JWTService
import org.knora.webapi.config.AppConfig
import org.knora.webapi.config.AppConfigForTestContainers
import org.knora.webapi.core.Logging
import org.knora.webapi.store.cacheservice.CacheServiceManager
import org.knora.webapi.store.cacheservice.impl.CacheServiceInMemImpl
import org.knora.webapi.store.iiif.IIIFServiceManager
import org.knora.webapi.store.iiif.impl.IIIFServiceSipiImpl
import org.knora.webapi.testcontainers.SipiTestContainer
import org.scalatest.BeforeAndAfterAll
import org.scalatest.matchers.should.Matchers
import org.scalatest.wordspec.AnyWordSpecLike
import zio.&
import zio.Runtime
import zio.ZEnvironment
import zio.ZIO
import zio.ZLayer
import scala.concurrent.Await
import scala.concurrent.ExecutionContext
import scala.concurrent.duration._
import scala.language.postfixOps
import scala.util.Failure
import scala.util.Success
import scala.util.Try
import app.ApplicationActor
import core.Core
import feature.{FeatureFactoryConfig, KnoraSettingsFeatureFactoryConfig, TestFeatureFactoryConfig}
import messages.StringFormatter
import messages.app.appmessages.{AppStart, SetAllowReloadOverHTTPState}
import messages.store.cacheservicemessages.CacheServiceFlushDB
import messages.store.triplestoremessages.{RdfDataObject, ResetRepositoryContent}
import messages.util.rdf.RdfFeatureFactory
import messages.util.{KnoraSystemInstances, ResponderData}
import messages.v2.responder.ontologymessages.LoadOntologiesRequestV2
import settings.{KnoraDispatchers, KnoraSettings, KnoraSettingsImpl, _}
import store.cacheservice.settings.CacheServiceSettings
import util.StartupUtils
object CoreSpec {
/*
Loads the following (first-listed are higher priority):
- system properties (e.g., -Dconfig.resource=fuseki.conf)
- test/resources/application.conf
- main/resources/application.conf
*/
val defaultConfig: Config = ConfigFactory.load()
/* Copied from: akka/akka-testkit/src/test/scala/akka/testkit/AkkaSpec.scala */
def getCallerName(clazz: Class[_]): String = {
val s = (Thread.currentThread.getStackTrace map (_.getClassName) drop 1)
.dropWhile(_ matches "(java.lang.Thread|.*CoreSpec.?$)")
val reduced = s.lastIndexWhere(_ == clazz.getName) match {
case -1 => s
case z => s drop (z + 1)
}
reduced.head.replaceFirst(""".*\.""", "").replaceAll("[^a-zA-Z_0-9]", "_")
}
}
abstract class CoreSpec(_system: ActorSystem)
extends TestKit(_system)
with Core
with StartupUtils
with AnyWordSpecLike
with Matchers
with BeforeAndAfterAll
with ImplicitSender {
/* constructors - individual tests can override the configuration by giving their own */
def this(name: String, config: Config) =
this(
ActorSystem(
name,
TestContainerFuseki.PortConfig.withFallback(ConfigFactory.load(config.withFallback(CoreSpec.defaultConfig)))
)
)
def this(config: Config) =
this(
ActorSystem(
CoreSpec.getCallerName(classOf[CoreSpec]),
TestContainerFuseki.PortConfig.withFallback(ConfigFactory.load(config.withFallback(CoreSpec.defaultConfig)))
)
)
def this(name: String) = this(ActorSystem(name, TestContainerFuseki.PortConfig.withFallback(ConfigFactory.load())))
def this() =
this(
ActorSystem(
CoreSpec.getCallerName(classOf[CoreSpec]),
TestContainerFuseki.PortConfig.withFallback(ConfigFactory.load())
)
)
/* needed by the core trait */
implicit lazy val settings: KnoraSettingsImpl = KnoraSettings(system)
implicit val materializer: Materializer = Materializer.matFromSystem(system)
implicit val executionContext: ExecutionContext = system.dispatchers.lookup(KnoraDispatchers.KnoraActorDispatcher)
// can be overridden in individual spec
lazy val rdfDataObjects = Seq.empty[RdfDataObject]
// needs to be initialized early on
StringFormatter.initForTest()
RdfFeatureFactory.init(settings)
val log: LoggingAdapter = akka.event.Logging(system, this.getClass)
// The ZIO runtime used to run functional effects
val runtime = Runtime.unsafeFromLayer(Logging.fromInfo)
// The effect for building a cache service manager and a IIIF service manager.
val managers = for {
csm <- ZIO.service[CacheServiceManager]
iiifsm <- ZIO.service[IIIFServiceManager]
appConfig <- ZIO.service[AppConfig]
} yield (csm, iiifsm, appConfig)
/**
* The effect layers which will be used to run the managers effect.
* Can be overriden in specs that need other implementations.
*/
lazy val effectLayers =
ZLayer.make[CacheServiceManager & IIIFServiceManager & AppConfig](
CacheServiceManager.layer,
CacheServiceInMemImpl.layer,
IIIFServiceManager.layer,
IIIFServiceSipiImpl.layer, // alternative: MockSipiImpl.layer
AppConfigForTestContainers.testcontainers,
JWTService.layer,
// FusekiTestContainer.layer,
SipiTestContainer.layer
)
/**
* Create both managers by unsafe running them.
*/
val (cacheServiceManager, iiifServiceManager, appConfig) =
runtime
.unsafeRun(
managers
.provide(
effectLayers
)
)
// start the Application Actor
lazy val appActor: ActorRef =
system.actorOf(
Props(new ApplicationActor(cacheServiceManager, iiifServiceManager, appConfig)),
name = APPLICATION_MANAGER_ACTOR_NAME
)
// The main application actor forwards messages to the responder manager and the store manager.
val responderManager: ActorRef = appActor
val storeManager: ActorRef = appActor
val responderData: ResponderData = ResponderData(
system = system,
appActor = appActor,
knoraSettings = settings,
cacheServiceSettings = new CacheServiceSettings(system.settings.config)
)
protected val defaultFeatureFactoryConfig: FeatureFactoryConfig = new TestFeatureFactoryConfig(
testToggles = Set.empty,
parent = new KnoraSettingsFeatureFactoryConfig(settings)
)
final override def beforeAll(): Unit = {
// set allow reload over http
appActor ! SetAllowReloadOverHTTPState(true)
// Start Knora, without reading data from the repository
appActor ! AppStart(ignoreRepository = true, requiresIIIFService = false)
// waits until knora is up and running
applicationStateRunning()
loadTestData(rdfDataObjects)
// memusage()
}
final override def afterAll(): Unit =
TestKit.shutdownActorSystem(system)
protected def loadTestData(rdfDataObjects: Seq[RdfDataObject]): Unit = {
logger.info("Loading test data started ...")
implicit val timeout: Timeout = Timeout(settings.defaultTimeout)
Try(Await.result(appActor ? ResetRepositoryContent(rdfDataObjects), 479999.milliseconds)) match {
case Success(res) => logger.info("... loading test data done.")
case Failure(e) => logger.error(s"Loading test data failed: ${e.getMessage}")
}
logger.info("Loading load ontologies into cache started ...")
Try(
Await.result(
appActor ? LoadOntologiesRequestV2(
featureFactoryConfig = defaultFeatureFactoryConfig,
requestingUser = KnoraSystemInstances.Users.SystemUser
),
1 minute
)
) match {
case Success(res) => logger.info("... loading ontologies into cache done.")
case Failure(e) => logger.error(s"Loading ontologies into cache failed: ${e.getMessage}")
}
logger.info("CacheServiceFlushDB started ...")
Try(Await.result(appActor ? CacheServiceFlushDB(KnoraSystemInstances.Users.SystemUser), 15 seconds)) match {
case Success(res) => logger.info("... CacheServiceFlushDB done.")
case Failure(e) => logger.error(s"CacheServiceFlushDB failed: ${e.getMessage}")
}
}
}