Skip to content

Commit b6511f9

Browse files
Merge pull request #66 from delphi-hub/feature/dbtest
Added tests for DatabaseInstanceDAO, fixed bugs in DatabaseInstanceDAO.
2 parents a54cd54 + bc9db2c commit b6511f9

File tree

5 files changed

+192
-7
lines changed

5 files changed

+192
-7
lines changed

build.sbt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,4 +36,6 @@ libraryDependencies ++= List(
3636
"org.slf4j" % "slf4j-nop" % "1.6.4"
3737
)
3838

39+
libraryDependencies += "com.h2database" % "h2" % "1.4.197"
40+
3941
trapExit := false

src/main/scala/de/upb/cs/swt/delphi/instanceregistry/daos/DatabaseInstanceDAO.scala

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,11 +28,10 @@ class DatabaseInstanceDAO (configuration : Configuration) extends InstanceDAO wi
2828
private val eventMaps : TableQuery[EventMaps] = TableQuery[EventMaps]
2929

3030
implicit val system : ActorSystem = Registry.system
31-
implicit val materializer : ActorMaterializer = ActorMaterializer()
31+
implicit val materializer : ActorMaterializer = Registry.materializer
3232
implicit val ec : ExecutionContext = system.dispatcher
3333

34-
val db = Database.forURL(configuration.databaseHost + configuration.databaseName, driver = configuration.databaseDriver, user = configuration.databaseUsername, password = configuration.databasePassword)
35-
34+
private var db = Database.forURL(configuration.databaseHost + configuration.databaseName, driver = configuration.databaseDriver, user = configuration.databaseUsername, password = configuration.databasePassword)
3635
override def addInstance(instance : Instance) : Try[Long] = {
3736

3837
val id = 0L //Will be set by DB
@@ -452,7 +451,7 @@ class DatabaseInstanceDAO (configuration : Configuration) extends InstanceDAO wi
452451
}
453452

454453
private def hasMatchingResultForInstance(id: Long): Boolean = {
455-
Await.result(db.run(instanceMatchingResults.filter(_.id === id).exists.result), Duration.Inf)
454+
Await.result(db.run(instanceMatchingResults.filter(_.instanceId === id).exists.result), Duration.Inf)
456455
}
457456

458457
private def hasInstanceEvents(id: Long) : Boolean = {
@@ -477,4 +476,9 @@ class DatabaseInstanceDAO (configuration : Configuration) extends InstanceDAO wi
477476
}
478477
}
479478

479+
def setDatabaseConfiguration(databaseHost: String = "", databaseName: String = "", databaseDriver: String = "", databaseUsername: String = "", databasePassword: String = "") ={
480+
db = Database.forURL(databaseHost + databaseName, driver = databaseDriver, user = databaseUsername, password = databasePassword)
481+
initialize()
482+
}
483+
480484
}

src/main/scala/de/upb/cs/swt/delphi/instanceregistry/daos/DynamicInstanceDAO.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ class DynamicInstanceDAO (configuration : Configuration) extends InstanceDAO wit
2828
private val instanceLinks: mutable.Set[InstanceLink] = new mutable.HashSet[InstanceLink]()
2929

3030
implicit val system : ActorSystem = Registry.system
31-
implicit val materializer : ActorMaterializer = ActorMaterializer()
31+
implicit val materializer : ActorMaterializer = Registry.materializer
3232
implicit val ec : ExecutionContext = system.dispatcher
3333

3434

src/main/scala/de/upb/cs/swt/delphi/instanceregistry/daos/Tables.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import java.sql.Timestamp
44
import akka.http.scaladsl.model.DateTime
55
import slick.jdbc.MySQLProfile
66
import slick.jdbc.MySQLProfile.api._
7-
import slick.sql.SqlProfile.ColumnOption.NotNull
7+
import slick.sql.SqlProfile.ColumnOption.{NotNull, SqlType}
88

99
class Instances(tag: Tag) extends Table[(Long, String, Long, String, String, Option[String], String, String)](tag, "instances") {
1010
def id = column[Long]("id", O.PrimaryKey, O.AutoInc) // This is the primary key column
@@ -31,7 +31,7 @@ class InstanceMatchingResults(tag: Tag) extends Table[(Long, Long, Boolean)](tag
3131
class InstanceEvents(tag: Tag) extends Table[(Long, String, DateTime, String)](tag, "instance_events") {
3232
def id = column[Long]("id", O.PrimaryKey, O.AutoInc) // This is the primary key column
3333
def eventType = column[String]("eventType", O.Length(100), NotNull)
34-
def timestamp = column[DateTime]("timestamp", NotNull)
34+
def timestamp = column[DateTime]("timestamp", SqlType("timestamp not null default CURRENT_TIMESTAMP"))
3535
def payload = column[String]("payload", O.Length(1000), NotNull)
3636

3737
def * = (id, eventType, timestamp, payload)
Lines changed: 179 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,179 @@
1+
package de.upb.cs.swt.delphi.instanceregistry.daos
2+
3+
import de.upb.cs.swt.delphi.instanceregistry.Configuration
4+
import de.upb.cs.swt.delphi.instanceregistry.io.swagger.client.model.InstanceEnums.{ComponentType, InstanceState}
5+
import de.upb.cs.swt.delphi.instanceregistry.io.swagger.client.model.LinkEnums.LinkState
6+
import de.upb.cs.swt.delphi.instanceregistry.io.swagger.client.model.{Instance, InstanceLink, RegistryEventFactory}
7+
import org.scalatest.{BeforeAndAfterEach, FlatSpec, Matchers}
8+
9+
class DatabaseInstanceDAOTest extends FlatSpec with Matchers with BeforeAndAfterEach{
10+
11+
val config = new Configuration()
12+
val dao : DatabaseInstanceDAO = new DatabaseInstanceDAO(config)
13+
dao.setDatabaseConfiguration("jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE;MODE=MYSQL","", "org.h2.Driver")
14+
before()
15+
16+
private def buildInstance(id : Int) : Instance = {
17+
Instance(Some(id), "https://localhost", 12345, "TestInstance", ComponentType.Crawler, None, InstanceState.Stopped, List.empty[String],
18+
List.empty[InstanceLink], List.empty[InstanceLink])
19+
}
20+
21+
def before() : Unit = {
22+
for(i <- 1 to 3){
23+
dao.addInstance(buildInstance(i))
24+
}
25+
}
26+
27+
"The instance DAO" must "be able to add an get an instance with a new id" in {
28+
val idOption = dao.addInstance(buildInstance(id = 42))
29+
assert(idOption.isSuccess)
30+
assert(dao.allInstances().size == 4)
31+
assert(dao.hasInstance(idOption.get))
32+
assert(dao.removeInstance(idOption.get).isSuccess)
33+
}
34+
35+
it must "not assign unique ids ignoring the ones provided by the parameter" in {
36+
val idOption = dao.addInstance(buildInstance(4))
37+
assert(idOption.isSuccess)
38+
assert(dao.allInstances().size == 4)
39+
assert(dao.hasInstance(idOption.get))
40+
assert(dao.removeInstance(idOption.get).isSuccess)
41+
}
42+
43+
it must "return true on hasInstance for any present id" in {
44+
for(i <- 1 to 3){
45+
assert(dao.hasInstance(i))
46+
}
47+
}
48+
49+
it must "return false on hasInstance for any id not present" in {
50+
assert(!dao.hasInstance(-1))
51+
assert(!dao.hasInstance(Long.MaxValue))
52+
assert(!dao.hasInstance(4))
53+
}
54+
55+
it must "return instances with the correct id on getInstance" in {
56+
for(i <- 1 to 3){
57+
val instance = dao.getInstance(i)
58+
assert(instance.isDefined)
59+
assert(instance.get.id.isDefined)
60+
assert(instance.get.id.get == i)
61+
}
62+
}
63+
64+
it must "return instance with the correct type on getInstanceOfType" in {
65+
val compTypeInstances = dao.getInstancesOfType(ComponentType.Crawler)
66+
assert(compTypeInstances.size == 3)
67+
68+
for(instance <- compTypeInstances){
69+
assert(instance.componentType == ComponentType.Crawler)
70+
}
71+
}
72+
73+
it must "Successfully added the Instance matching result" in {
74+
val idOption = dao.addInstance(buildInstance(6))
75+
dao.addMatchingResult(idOption.get, true)
76+
assert(dao.getMatchingResultsFor(idOption.get).isSuccess)
77+
}
78+
79+
it must "have an empty list of matching results for newly added instances" in {
80+
dao.removeInstance(6)
81+
assert(dao.getMatchingResultsFor(6).isFailure)
82+
}
83+
84+
it must "keep the correct order of matching results posted" in {
85+
assert(dao.addMatchingResult(2, matchingSuccessful = true).isSuccess)
86+
assert(dao.addMatchingResult(2, matchingSuccessful = true).isSuccess)
87+
assert(dao.addMatchingResult(2, matchingSuccessful = false).isSuccess)
88+
89+
assert(dao.getMatchingResultsFor(2).isSuccess)
90+
assert(dao.getMatchingResultsFor(2).get.head)
91+
assert(dao.getMatchingResultsFor(2).get (1))
92+
assert(!dao.getMatchingResultsFor(2).get (2))
93+
94+
}
95+
96+
it must "remove the matching results when the instance is removed" in {
97+
val idOption = dao.addInstance(buildInstance(7))
98+
assert(dao.removeInstance(idOption.get).isSuccess)
99+
assert(dao.getMatchingResultsFor(idOption.get).isFailure)
100+
}
101+
102+
it must "be able to change the state for arbitrary state transitions" in {
103+
assert(dao.getInstance(1).get.instanceState == InstanceState.Stopped)
104+
assert(dao.setStateFor(1, InstanceState.Failed).isSuccess)
105+
assert(dao.getInstance(1).get.instanceState == InstanceState.Failed)
106+
assert(dao.setStateFor(1, InstanceState.Running).isSuccess)
107+
assert(dao.getInstance(1).get.instanceState == InstanceState.Running)
108+
}
109+
110+
it must "fail when setting state for invalid ids" in {
111+
assert(dao.setStateFor(42, InstanceState.Failed).isFailure)
112+
assert(dao.setStateFor(Int.MaxValue, InstanceState.Running).isFailure)
113+
}
114+
115+
it must "fail to get docker ids from instances without any docker id" in {
116+
assert(dao.getDockerIdFor(1).isFailure)
117+
assert(dao.getDockerIdFor(2).isFailure)
118+
}
119+
120+
it must "return the correct docker ids for instances with a docker id" in {
121+
val idOption = dao.addInstance(Instance(Some(42), "http://localhost", 33449, "AnyName",
122+
ComponentType.WebApi, Some("dockerId"), InstanceState.Running, List.empty[String], List.empty[InstanceLink], List.empty[InstanceLink] ))
123+
assert(idOption.isSuccess)
124+
assert(dao.getDockerIdFor(idOption.get).isSuccess)
125+
assert(dao.getDockerIdFor(idOption.get).get.equals("dockerId"))
126+
dao.removeInstance(idOption.get)
127+
}
128+
129+
it must "add events only to instances that have been registered" in {
130+
assert(dao.getEventsFor(1).isFailure)
131+
//assert(dao.getEventsFor(1).get.isEmpty)
132+
133+
val eventToAdd = RegistryEventFactory.createInstanceAddedEvent(dao.getInstance(1).get)
134+
assert(dao.addEventFor(-1, eventToAdd).isFailure)
135+
assert(dao.addEventFor(1, eventToAdd).isSuccess)
136+
assert(dao.getEventsFor(1).get.size == 1)
137+
assert(dao.getEventsFor(1).get.head == eventToAdd)
138+
}
139+
140+
it must "verify the presence of instance ids when a link is added" in {
141+
assert(dao.addLink(InstanceLink(-1,2, LinkState.Assigned)).isFailure)
142+
assert(dao.addLink(InstanceLink(42, Integer.MAX_VALUE, LinkState.Assigned)).isFailure)
143+
assert(dao.addLink(InstanceLink(2,3, LinkState.Assigned)).isSuccess)
144+
assert(dao.getLinksFrom(2).size == 1)
145+
}
146+
147+
it must "update old links in state 'Assigned' on adding a new assigned link." in {
148+
assert(dao.addLink(InstanceLink(1,2, LinkState.Assigned)).isSuccess)
149+
assert(dao.getLinksFrom(1, Some(LinkState.Assigned)).size == 1)
150+
assert(dao.addLink(InstanceLink(1,3, LinkState.Assigned)).isSuccess)
151+
152+
assert(dao.getLinksFrom(1, Some(LinkState.Outdated)).size == 1)
153+
assert(dao.getLinksFrom(1, Some(LinkState.Outdated)).head.idTo == 2)
154+
155+
assert(dao.getLinksFrom(1, Some(LinkState.Assigned)).size == 1)
156+
assert(dao.getLinksFrom(1, Some(LinkState.Assigned)).head.idTo == 3)
157+
}
158+
159+
it must "remove instances that are present in the DAO" in {
160+
for(i <- 1 to 3){
161+
assert(dao.removeInstance(i).isSuccess)
162+
assert(!dao.hasInstance(i))
163+
}
164+
assert(dao.allInstances().isEmpty)
165+
}
166+
167+
it must "not change the data on removing invalid IDs" in {
168+
assert(dao.removeInstance(-1).isFailure)
169+
assert(dao.removeInstance(Long.MaxValue).isFailure)
170+
assert(dao.removeInstance(4).isFailure)
171+
}
172+
173+
it must "remove all instance on removeAll" in {
174+
before()
175+
dao.removeAll()
176+
assert(dao.allInstances().isEmpty)
177+
}
178+
179+
}

0 commit comments

Comments
 (0)