~jan0sch/smederee
Showing details for patch cdf33e46fd5bcb52a047fb53e6b221b5bdb12a44.
diff -rN -u old-smederee/modules/hub/src/test/scala/de/smederee/hub/DoobieVcsMetadataRepositoryTest.scala new-smederee/modules/hub/src/test/scala/de/smederee/hub/DoobieVcsMetadataRepositoryTest.scala --- old-smederee/modules/hub/src/test/scala/de/smederee/hub/DoobieVcsMetadataRepositoryTest.scala 2025-01-10 21:16:53.831805179 +0000 +++ new-smederee/modules/hub/src/test/scala/de/smederee/hub/DoobieVcsMetadataRepositoryTest.scala 2025-01-10 21:16:53.831805179 +0000 @@ -6,11 +6,11 @@ package de.smederee.hub +import cats.data.NonEmptyList import cats.effect.* import cats.syntax.all.* import de.smederee.TestTags.* import de.smederee.email.EmailAddress -import de.smederee.hub.Generators.* import de.smederee.hub.Generators.given import de.smederee.hub.VcsMetadataRepositoriesOrdering.* import de.smederee.security.* @@ -56,323 +56,302 @@ } test("createFork must work correctly".tag(NeedsDatabase)) { - (genValidAccounts.suchThat(_.size > 4).sample, genValidVcsRepositories.suchThat(_.size > 4).sample) match { - case (Some(accounts), Some(repositories)) => - val vcsRepositories = accounts.zip(repositories).map { tuple => - val (account, repo) = tuple - repo.copy(owner = account.toVcsRepositoryOwner) + PropF.forAllF { (accounts: NonEmptyList[Account], repositories: NonEmptyList[VcsRepository]) => + val vcsRepositories = accounts.zip(repositories).map { tuple => + val (account, repo) = tuple + repo.copy(owner = account.toVcsRepositoryOwner) + } + val numberOfForks = + if ((vcsRepositories.tail.size / 2) > 5) { + 5 + } else { + vcsRepositories.tail.size / 2 } - val dbConfig = configuration.database - val tx = Transactor.fromDriverManager[IO]( - driver = dbConfig.driver, - url = dbConfig.url, - user = dbConfig.user, - password = dbConfig.pass, - logHandler = None + val dbConfig = configuration.database + val tx = Transactor.fromDriverManager[IO]( + driver = dbConfig.driver, + url = dbConfig.url, + user = dbConfig.user, + password = dbConfig.pass, + logHandler = None + ) + val repo = new DoobieVcsMetadataRepository[IO](tx) + val test = for { + _ <- accounts.traverse(account => + createAccount(account, PasswordHash("I am not a password hash!"), None, None) ) - val repo = new DoobieVcsMetadataRepository[IO](tx) - val test = for { - _ <- accounts.traverse(account => - createAccount(account, PasswordHash("I am not a password hash!"), None, None) - ) - written <- vcsRepositories.traverse(repo.createVcsRepository) - original <- vcsRepositories.headOption.traverse(vcsRepository => - loadVcsRepositoryId(vcsRepository.owner.uid, vcsRepository.name) - ) - toFork <- vcsRepositories.drop(1).take(5).traverse { vcsRepository => - loadVcsRepositoryId(vcsRepository.owner.uid, vcsRepository.name) - } - forked <- (original, toFork) match { - case (Some(Some(originalId)), forkIds) => - forkIds.flatten.traverse(id => repo.createFork(originalId, id)) - case _ => IO.pure(List.empty) - } - foundForks <- original match { - case Some(Some(originalId)) => findForks(originalId) - case _ => IO.pure(List.empty) - } - } yield (written, forked, foundForks) - test.map { result => - val (written, forked, foundForks) = result - assert(written.sum === vcsRepositories.size, "Test repository data was not written to database!") - assert( - forked.sum === vcsRepositories.drop(1).take(5).size, - "Number of created forks does not match!" - ) - assert( - foundForks.size === vcsRepositories.drop(1).take(5).size, - "Number of found forks does not match!" - ) - } - case _ => fail("Could not generate data samples!") + written <- vcsRepositories.traverse(repo.createVcsRepository) + original <- loadVcsRepositoryId(vcsRepositories.head.owner.uid, vcsRepositories.head.name) + toFork <- vcsRepositories.tail.take(numberOfForks).traverse { vcsRepository => + loadVcsRepositoryId(vcsRepository.owner.uid, vcsRepository.name) + } + forked <- (original, toFork) match { + case (Some(originalId), forkIds) => + forkIds.flatten.traverse(id => repo.createFork(originalId, id)) + case _ => IO.pure(List.empty) + } + foundForks <- original match { + case Some(originalId) => findForks(originalId) + case _ => IO.pure(List.empty) + } + } yield (written.toList.sum, forked, foundForks) + test.start.flatMap(_.joinWithNever).map { result => + val (written, forked, foundForks) = result + assert(written === vcsRepositories.size, "Test repository data was not written to database!") + assert(forked.sum === numberOfForks, "Number of created forks does not match!") + assert(foundForks.size === numberOfForks, "Number of found forks does not match!") + } } } test("createVcsRepository must create a repository entry".tag(NeedsDatabase)) { - (genValidAccount.sample, genValidVcsRepository.sample) match { - case (Some(account), Some(repository)) => - val vcsRepository = repository.copy(owner = account.toVcsRepositoryOwner) - val dbConfig = configuration.database - val tx = Transactor.fromDriverManager[IO]( - driver = dbConfig.driver, - url = dbConfig.url, - user = dbConfig.user, - password = dbConfig.pass, - logHandler = None - ) - val repo = new DoobieVcsMetadataRepository[IO](tx) - val test = for { - _ <- createAccount(account, PasswordHash("I am not a password hash!"), None, None) - written <- repo.createVcsRepository(vcsRepository) - } yield written - test.map { written => - assert(written === 1, "Creating a vcs repository must modify one database row!") - } - case _ => fail("Could not generate data samples!") + PropF.forAllF { (account: Account, repository: VcsRepository) => + val vcsRepository = repository.copy(owner = account.toVcsRepositoryOwner) + val dbConfig = configuration.database + val tx = Transactor.fromDriverManager[IO]( + driver = dbConfig.driver, + url = dbConfig.url, + user = dbConfig.user, + password = dbConfig.pass, + logHandler = None + ) + val repo = new DoobieVcsMetadataRepository[IO](tx) + val test = for { + _ <- createAccount(account, PasswordHash("I am not a password hash!"), None, None) + written <- repo.createVcsRepository(vcsRepository) + } yield written + test.start.flatMap(_.joinWithNever).map { written => + assert(written === 1, "Creating a vcs repository must modify one database row!") + } } } test("createVcsRepository must fail if the user does not exist".tag(NeedsDatabase)) { - genValidVcsRepository.sample match { - case Some(repository) => - val dbConfig = configuration.database - val tx = Transactor.fromDriverManager[IO]( - driver = dbConfig.driver, - url = dbConfig.url, - user = dbConfig.user, - password = dbConfig.pass, - logHandler = None - ) - val repo = new DoobieVcsMetadataRepository[IO](tx) - val test = for { - written <- repo.createVcsRepository(repository) - } yield written - test.attempt.map(result => assert(result.isLeft)) - case _ => fail("Could not generate data samples!") + PropF.forAllF { (repository: VcsRepository) => + val dbConfig = configuration.database + val tx = Transactor.fromDriverManager[IO]( + driver = dbConfig.driver, + url = dbConfig.url, + user = dbConfig.user, + password = dbConfig.pass, + logHandler = None + ) + val repo = new DoobieVcsMetadataRepository[IO](tx) + val test = for { + written <- repo.createVcsRepository(repository) + } yield written + test.attempt.map(result => assert(result.isLeft)) } } test("createVcsRepository must fail if a repository with the same name exists".tag(NeedsDatabase)) { - (genValidAccount.sample, genValidVcsRepository.sample) match { - case (Some(account), Some(repository)) => - val vcsRepository = repository.copy(owner = account.toVcsRepositoryOwner) - val dbConfig = configuration.database - val tx = Transactor.fromDriverManager[IO]( - driver = dbConfig.driver, - url = dbConfig.url, - user = dbConfig.user, - password = dbConfig.pass, - logHandler = None - ) - val repo = new DoobieVcsMetadataRepository[IO](tx) - val test = for { - _ <- createAccount(account, PasswordHash("I am not a password hash!"), None, None) - _ <- repo.createVcsRepository(vcsRepository) - written <- repo.createVcsRepository(vcsRepository) - } yield written - test.attempt.map(result => assert(result.isLeft)) - case _ => fail("Could not generate data samples!") + PropF.forAllF { (account: Account, repository: VcsRepository) => + val vcsRepository = repository.copy(owner = account.toVcsRepositoryOwner) + val dbConfig = configuration.database + val tx = Transactor.fromDriverManager[IO]( + driver = dbConfig.driver, + url = dbConfig.url, + user = dbConfig.user, + password = dbConfig.pass, + logHandler = None + ) + val repo = new DoobieVcsMetadataRepository[IO](tx) + val test = for { + _ <- createAccount(account, PasswordHash("I am not a password hash!"), None, None) + _ <- repo.createVcsRepository(vcsRepository) + written <- repo.createVcsRepository(vcsRepository) + } yield written + test.attempt.map(result => assert(result.isLeft)) } } test("findVcsRepository must return an existing repository".tag(NeedsDatabase)) { - (genValidAccount.sample, genValidVcsRepository.sample) match { - case (Some(account), Some(repository)) => - val vcsRepository = repository.copy(owner = account.toVcsRepositoryOwner) - val dbConfig = configuration.database - val tx = Transactor.fromDriverManager[IO]( - driver = dbConfig.driver, - url = dbConfig.url, - user = dbConfig.user, - password = dbConfig.pass, - logHandler = None - ) - val repo = new DoobieVcsMetadataRepository[IO](tx) - val test = for { - _ <- createAccount(account, PasswordHash("I am not a password hash!"), None, None) - written <- repo.createVcsRepository(vcsRepository) - foundRepo <- repo.findVcsRepository(vcsRepository.owner, vcsRepository.name) - } yield (written, foundRepo) - test.map { result => - val (written, foundRepo) = result - assert(written === 1, "Test repository data was not written to database!") - foundRepo match { - case None => fail("Repository was not found!") - case Some(repo) => assert(repo === vcsRepository) - } + PropF.forAllF { (account: Account, repository: VcsRepository) => + val vcsRepository = repository.copy(owner = account.toVcsRepositoryOwner) + val dbConfig = configuration.database + val tx = Transactor.fromDriverManager[IO]( + driver = dbConfig.driver, + url = dbConfig.url, + user = dbConfig.user, + password = dbConfig.pass, + logHandler = None + ) + val repo = new DoobieVcsMetadataRepository[IO](tx) + val test = for { + _ <- createAccount(account, PasswordHash("I am not a password hash!"), None, None) + written <- repo.createVcsRepository(vcsRepository) + foundRepo <- repo.findVcsRepository(vcsRepository.owner, vcsRepository.name) + } yield (written, foundRepo) + test.start.flatMap(_.joinWithNever).map { result => + val (written, foundRepo) = result + assert(written === 1, "Test repository data was not written to database!") + foundRepo match { + case None => fail("Repository was not found!") + case Some(repo) => assert(repo === vcsRepository) } - case _ => fail("Could not generate data samples!") + } } } test("findVcsRepositoryBranches must return all branches".tag(NeedsDatabase)) { - (genValidAccounts.suchThat(_.size > 4).sample, genValidVcsRepositories.suchThat(_.size > 4).sample) match { - case (Some(accounts), Some(repositories)) => - val vcsRepositories = accounts.zip(repositories).map { tuple => - val (account, repo) = tuple - repo.copy(owner = account.toVcsRepositoryOwner) - } - val dbConfig = configuration.database - val tx = Transactor.fromDriverManager[IO]( - driver = dbConfig.driver, - url = dbConfig.url, - user = dbConfig.user, - password = dbConfig.pass, - logHandler = None + PropF.forAllF { (accounts: NonEmptyList[Account], repositories: NonEmptyList[VcsRepository]) => + val vcsRepositories = accounts.zip(repositories).map { tuple => + val (account, repo) = tuple + repo.copy(owner = account.toVcsRepositoryOwner) + } + val numberOfForks = + if ((vcsRepositories.tail.size / 2) > 5) { + 5 + } else { + vcsRepositories.tail.size / 2 + } + val dbConfig = configuration.database + val tx = Transactor.fromDriverManager[IO]( + driver = dbConfig.driver, + url = dbConfig.url, + user = dbConfig.user, + password = dbConfig.pass, + logHandler = None + ) + val repo = new DoobieVcsMetadataRepository[IO](tx) + val test = for { + _ <- accounts.traverse(account => + createAccount(account, PasswordHash("I am not a password hash!"), None, None) ) - val repo = new DoobieVcsMetadataRepository[IO](tx) - val test = for { - _ <- accounts.traverse(account => - createAccount(account, PasswordHash("I am not a password hash!"), None, None) - ) - written <- vcsRepositories.traverse(repo.createVcsRepository) - original <- vcsRepositories.headOption.traverse(vcsRepository => - loadVcsRepositoryId(vcsRepository.owner.uid, vcsRepository.name) - ) - toFork <- vcsRepositories.drop(1).take(5).traverse { vcsRepository => - loadVcsRepositoryId(vcsRepository.owner.uid, vcsRepository.name) - } - forked <- (original, toFork) match { - case (Some(Some(originalId)), forkIds) => - forkIds.flatten.traverse(id => repo.createFork(originalId, id)) - case _ => IO.pure(List.empty) - } - foundForks <- original match { - case Some(Some(originalId)) => repo.findVcsRepositoryBranches(originalId).compile.toList - case _ => IO.pure(List.empty) - } - } yield (written, forked, foundForks) - test.map { result => - val (written, forked, foundForks) = result - assert(written.sum === vcsRepositories.size, "Test repository data was not written to database!") - assert( - forked.sum === vcsRepositories.drop(1).take(5).size, - "Number of created forks does not match!" - ) - assert( - foundForks.size === vcsRepositories.drop(1).take(5).size, - "Number of found forks does not match!" - ) - foundForks.zip(vcsRepositories.drop(1).take(5)).map { tuple => - val ((ownerName, repoName), repo) = tuple - assertEquals(ownerName, repo.owner.name) - assertEquals(repoName, repo.name) - } + written <- vcsRepositories.traverse(repo.createVcsRepository) + original <- loadVcsRepositoryId(vcsRepositories.head.owner.uid, vcsRepositories.head.name) + toFork <- vcsRepositories.tail.take(numberOfForks).traverse { vcsRepository => + loadVcsRepositoryId(vcsRepository.owner.uid, vcsRepository.name) + } + forked <- (original, toFork) match { + case (Some(originalId), forkIds) => + forkIds.flatten.traverse(id => repo.createFork(originalId, id)) + case _ => IO.pure(List.empty) + } + foundForks <- original match { + case Some(originalId) => repo.findVcsRepositoryBranches(originalId).compile.toList + case _ => IO.pure(List.empty) + } + } yield (written.toList.sum, forked, foundForks) + test.start.flatMap(_.joinWithNever).map { result => + val (written, forked, foundForks) = result + assert(written === vcsRepositories.size, "Test repository data was not written to database!") + assert(forked.sum === numberOfForks, "Number of created forks does not match!") + assert(foundForks.size === numberOfForks, "Number of found forks does not match!") + foundForks.zip(vcsRepositories.tail.take(numberOfForks)).foreach { tuple => + val ((ownerName, repoName), repo) = tuple + assertEquals(ownerName, repo.owner.name) + assertEquals(repoName, repo.name) } - case _ => fail("Could not generate data samples!") + } } } test("loadVcsRepositoryId must return the id of an existing repository".tag(NeedsDatabase)) { - (genValidAccount.sample, genValidVcsRepository.sample) match { - case (Some(account), Some(repository)) => - val vcsRepository = repository.copy(owner = account.toVcsRepositoryOwner) - val dbConfig = configuration.database - val tx = Transactor.fromDriverManager[IO]( - driver = dbConfig.driver, - url = dbConfig.url, - user = dbConfig.user, - password = dbConfig.pass, - logHandler = None - ) - val repo = new DoobieVcsMetadataRepository[IO](tx) - val test = for { - _ <- createAccount(account, PasswordHash("I am not a password hash!"), None, None) - writtenRows <- repo.createVcsRepository(vcsRepository) - writtenId <- loadVcsRepositoryId(vcsRepository.owner.uid, vcsRepository.name) - foundId <- repo.findVcsRepositoryId(vcsRepository.owner, vcsRepository.name) - } yield (writtenRows, writtenId, foundId) - test.map { result => - val (written, writtenId, foundId) = result - assert(written === 1, "Test repository data was not written to database!") - assert(writtenId.nonEmpty) - assert(foundId.nonEmpty) - assert(writtenId === foundId) - } - case _ => fail("Could not generate data samples!") + PropF.forAllF { (account: Account, repository: VcsRepository) => + val vcsRepository = repository.copy(owner = account.toVcsRepositoryOwner) + val dbConfig = configuration.database + val tx = Transactor.fromDriverManager[IO]( + driver = dbConfig.driver, + url = dbConfig.url, + user = dbConfig.user, + password = dbConfig.pass, + logHandler = None + ) + val repo = new DoobieVcsMetadataRepository[IO](tx) + val test = for { + _ <- createAccount(account, PasswordHash("I am not a password hash!"), None, None) + writtenRows <- repo.createVcsRepository(vcsRepository) + writtenId <- loadVcsRepositoryId(vcsRepository.owner.uid, vcsRepository.name) + foundId <- repo.findVcsRepositoryId(vcsRepository.owner, vcsRepository.name) + } yield (writtenRows, writtenId, foundId) + test.start.flatMap(_.joinWithNever).map { result => + val (written, writtenId, foundId) = result + assert(written === 1, "Test repository data was not written to database!") + assert(writtenId.nonEmpty) + assert(foundId.nonEmpty) + assert(writtenId === foundId) + } } } test("findVcsRepositoryOwner must return the correct account".tag(NeedsDatabase)) { - genValidAccounts.sample match { - case Some(accounts) => - val expectedOwner = accounts(scala.util.Random.nextInt(accounts.size)).toVcsRepositoryOwner - val dbConfig = configuration.database - val tx = Transactor.fromDriverManager[IO]( - driver = dbConfig.driver, - url = dbConfig.url, - user = dbConfig.user, - password = dbConfig.pass, - logHandler = None + PropF.forAllF { (accounts: NonEmptyList[Account]) => + val expectedOwner = accounts.toList(scala.util.Random.nextInt(accounts.size)).toVcsRepositoryOwner + val dbConfig = configuration.database + val tx = Transactor.fromDriverManager[IO]( + driver = dbConfig.driver, + url = dbConfig.url, + user = dbConfig.user, + password = dbConfig.pass, + logHandler = None + ) + val repo = new DoobieVcsMetadataRepository[IO](tx) + val test = for { + written <- accounts.traverse(account => + createAccount(account, PasswordHash("I am not a password hash!"), None, None) ) - val repo = new DoobieVcsMetadataRepository[IO](tx) - val test = for { - written <- accounts.traverse(account => - createAccount(account, PasswordHash("I am not a password hash!"), None, None) - ) - foundOwner <- repo.findVcsRepositoryOwner(expectedOwner.name) - } yield (written, foundOwner) - test.map { result => - val (written, foundOwner) = result - assert( - written.filter(_ === 1).size === written.size, - "Not all test repository data was not written to database!" - ) - foundOwner match { - case None => fail("Vcs repository owner not found!") - case Some(owner) => assertEquals(owner, expectedOwner) - } + foundOwner <- repo.findVcsRepositoryOwner(expectedOwner.name) + } yield (written, foundOwner) + test.start.flatMap(_.joinWithNever).map { result => + val (written, foundOwner) = result + assert( + written.filter(_ === 1).size === written.size, + "Not all test repository data was not written to database!" + ) + foundOwner match { + case None => fail("Vcs repository owner not found!") + case Some(owner) => assertEquals(owner, expectedOwner) } - case _ => fail("Could not generate data samples!") + } } } test("findVcsRepositoryParentFork must return the parent repository if it exists".tag(NeedsDatabase)) { - (genValidAccounts.suchThat(_.size > 4).sample, genValidVcsRepositories.suchThat(_.size > 4).sample) match { - case (Some(accounts), Some(repositories)) => - val vcsRepositories = accounts.zip(repositories).map { tuple => - val (account, repo) = tuple - repo.copy(owner = account.toVcsRepositoryOwner) - } - val dbConfig = configuration.database - val tx = Transactor.fromDriverManager[IO]( - driver = dbConfig.driver, - url = dbConfig.url, - user = dbConfig.user, - password = dbConfig.pass, - logHandler = None + PropF.forAllF { (accounts: NonEmptyList[Account], repositories: NonEmptyList[VcsRepository]) => + val vcsRepositories = accounts.zip(repositories).map { tuple => + val (account, repo) = tuple + repo.copy(owner = account.toVcsRepositoryOwner) + } + val numberOfForks = + if ((vcsRepositories.tail.size / 2) > 5) { + 5 + } else { + vcsRepositories.tail.size / 2 + } + val dbConfig = configuration.database + val tx = Transactor.fromDriverManager[IO]( + driver = dbConfig.driver, + url = dbConfig.url, + user = dbConfig.user, + password = dbConfig.pass, + logHandler = None + ) + val repo = new DoobieVcsMetadataRepository[IO](tx) + val test = for { + _ <- accounts.traverse(account => + createAccount(account, PasswordHash("I am not a password hash!"), None, None) ) - val repo = new DoobieVcsMetadataRepository[IO](tx) - val test = for { - _ <- accounts.traverse(account => - createAccount(account, PasswordHash("I am not a password hash!"), None, None) - ) - written <- vcsRepositories.traverse(repo.createVcsRepository) - original <- vcsRepositories.headOption.traverse(vcsRepository => - loadVcsRepositoryId(vcsRepository.owner.uid, vcsRepository.name) - ) - toFork <- vcsRepositories.drop(1).take(5).traverse { vcsRepository => - loadVcsRepositoryId(vcsRepository.owner.uid, vcsRepository.name) - } - forked <- (original, toFork) match { - case (Some(Some(originalId)), forkIds) => - forkIds.flatten.traverse(id => repo.createFork(originalId, id)) - case _ => IO.pure(List.empty) - } - foundParents <- vcsRepositories.drop(1).take(5).traverse { vcsRepository => - repo.findVcsRepositoryParentFork(vcsRepository.owner, vcsRepository.name) - } - } yield (written, forked, vcsRepositories.headOption, foundParents) - test.map { result => - val (written, forked, original, foundParents) = result - assert(written.sum === vcsRepositories.size, "Test repository data was not written to database!") - assert( - forked.sum === vcsRepositories.drop(1).take(5).size, - "Number of created forks does not match!" - ) - assert(foundParents.forall(_ === original), "Parent vcs repository not matching!") - } - case _ => fail("Could not generate data samples!") + written <- vcsRepositories.traverse(repo.createVcsRepository) + original <- loadVcsRepositoryId(vcsRepositories.head.owner.uid, vcsRepositories.head.name) + toFork <- vcsRepositories.tail.take(numberOfForks).traverse { vcsRepository => + loadVcsRepositoryId(vcsRepository.owner.uid, vcsRepository.name) + } + forked <- (original, toFork) match { + case (Some(originalId), forkIds) => + forkIds.flatten.traverse(id => repo.createFork(originalId, id)) + case _ => IO.pure(List.empty) + } + foundParents <- vcsRepositories.tail.take(numberOfForks).traverse { vcsRepository => + repo.findVcsRepositoryParentFork(vcsRepository.owner, vcsRepository.name) + } + } yield (written.toList.sum, forked.toList.sum, vcsRepositories.head.some, foundParents) + test.start.flatMap(_.joinWithNever).map { result => + val (written, forked, original, foundParents) = result + assert(written === vcsRepositories.size, "Test repository data was not written to database!") + assert(forked === numberOfForks, "Number of created forks does not match!") + assert(foundParents.forall(_ === original), "Parent vcs repository not matching!") + } } } @@ -434,239 +413,224 @@ } test("listAllRepositories must return only public repositories for guest users".tag(NeedsDatabase)) { - (genValidAccount.sample, genValidVcsRepositories.sample) match { - case (Some(account), Some(repositories)) => - val vcsRepositories = repositories - val accounts = vcsRepositories.map(repo => - Account( - repo.owner.uid, - repo.owner.name, - EmailAddress(s"${repo.owner.name}@example.com"), - account.fullName, - validatedEmail = true, - None - ) + PropF.forAllF { (account: Account, repositories: NonEmptyList[VcsRepository]) => + val vcsRepositories = repositories.toList + val accounts = vcsRepositories.map(repo => + Account( + repo.owner.uid, + repo.owner.name, + EmailAddress(s"${repo.owner.name}@example.com"), + account.fullName, + validatedEmail = true, + None ) - val expectedRepoList = vcsRepositories.filter(_.isPrivate === false) - val dbConfig = configuration.database - val tx = Transactor.fromDriverManager[IO]( - driver = dbConfig.driver, - url = dbConfig.url, - user = dbConfig.user, - password = dbConfig.pass, - logHandler = None + ) + val expectedRepoList = vcsRepositories.filter(_.isPrivate === false) + val dbConfig = configuration.database + val tx = Transactor.fromDriverManager[IO]( + driver = dbConfig.driver, + url = dbConfig.url, + user = dbConfig.user, + password = dbConfig.pass, + logHandler = None + ) + val repo = new DoobieVcsMetadataRepository[IO](tx) + val test = for { + _ <- createAccount(account, PasswordHash("I am not a password hash!"), None, None) + _ <- accounts.traverse(account => + createAccount(account, PasswordHash("I am not a password hash!"), None, None) + ) + written <- vcsRepositories.traverse(vcsRepository => repo.createVcsRepository(vcsRepository)) + foundRepos <- repo.listAllRepositories(None)(NameAscending).compile.toList + } yield (written, foundRepos) + test.start.flatMap(_.joinWithNever).map { result => + val (written, foundRepos) = result + assert( + written.filter(_ === 1).size === written.size, + "Not all test repository data was written to database!" ) - val repo = new DoobieVcsMetadataRepository[IO](tx) - val test = for { - _ <- createAccount(account, PasswordHash("I am not a password hash!"), None, None) - _ <- accounts.traverse(account => - createAccount(account, PasswordHash("I am not a password hash!"), None, None) - ) - written <- vcsRepositories.traverse(vcsRepository => repo.createVcsRepository(vcsRepository)) - foundRepos <- repo.listAllRepositories(None)(NameAscending).compile.toList - } yield (written, foundRepos) - test.map { result => - val (written, foundRepos) = result - assert( - written.filter(_ === 1).size === written.size, - "Not all test repository data was written to database!" - ) - assertEquals(foundRepos.size, expectedRepoList.size) - } - - case _ => fail("Could not generate data samples!") + assertEquals(foundRepos.size, expectedRepoList.size) + } } } test("listAllRepositories must return only public repositories of others for any user".tag(NeedsDatabase)) { - (genValidAccount.sample, genValidVcsRepositories.sample) match { - case (Some(account), Some(repositories)) => - val vcsRepositories = repositories - val accounts = vcsRepositories.map(repo => - Account( - repo.owner.uid, - repo.owner.name, - EmailAddress(s"${repo.owner.name}@example.com"), - account.fullName, - validatedEmail = true, - None - ) + PropF.forAllF { (account: Account, repositories: NonEmptyList[VcsRepository]) => + val vcsRepositories = repositories.toList + val accounts = vcsRepositories.map(repo => + Account( + repo.owner.uid, + repo.owner.name, + EmailAddress(s"${repo.owner.name}@example.com"), + account.fullName, + validatedEmail = true, + None ) - val expectedRepoList = vcsRepositories.filter(_.isPrivate === false) - val dbConfig = configuration.database - val tx = Transactor.fromDriverManager[IO]( - driver = dbConfig.driver, - url = dbConfig.url, - user = dbConfig.user, - password = dbConfig.pass, - logHandler = None + ) + val expectedRepoList = vcsRepositories.filter(_.isPrivate === false) + val dbConfig = configuration.database + val tx = Transactor.fromDriverManager[IO]( + driver = dbConfig.driver, + url = dbConfig.url, + user = dbConfig.user, + password = dbConfig.pass, + logHandler = None + ) + val repo = new DoobieVcsMetadataRepository[IO](tx) + val test = for { + _ <- createAccount(account, PasswordHash("I am not a password hash!"), None, None) + _ <- accounts.traverse(account => + createAccount(account, PasswordHash("I am not a password hash!"), None, None) + ) + written <- vcsRepositories.traverse(vcsRepository => repo.createVcsRepository(vcsRepository)) + foundRepos <- repo.listAllRepositories(account.some)(NameDescending).compile.toList + } yield (written, foundRepos) + test.start.flatMap(_.joinWithNever).map { result => + val (written, foundRepos) = result + assert( + written.filter(_ === 1).size === written.size, + "Not all test repository data was written to database!" ) - val repo = new DoobieVcsMetadataRepository[IO](tx) - val test = for { - _ <- createAccount(account, PasswordHash("I am not a password hash!"), None, None) - _ <- accounts.traverse(account => - createAccount(account, PasswordHash("I am not a password hash!"), None, None) - ) - written <- vcsRepositories.traverse(vcsRepository => repo.createVcsRepository(vcsRepository)) - foundRepos <- repo.listAllRepositories(account.some)(NameDescending).compile.toList - } yield (written, foundRepos) - test.map { result => - val (written, foundRepos) = result - assert( - written.filter(_ === 1).size === written.size, - "Not all test repository data was written to database!" - ) - assertEquals(foundRepos.size, expectedRepoList.size) - } - - case _ => fail("Could not generate data samples!") + assertEquals(foundRepos.size, expectedRepoList.size) + } } } test("listAllRepositories must include all private repositories of the user".tag(NeedsDatabase)) { - (genValidAccount.sample, genValidVcsRepositories.sample) match { - case (Some(account), Some(repositories)) => - val privateRepos = - repositories.filter(_.isPrivate === true).map(_.copy(owner = account.toVcsRepositoryOwner)) - val publicRepos = repositories.filter(_.isPrivate === false) - val vcsRepositories = privateRepos ::: publicRepos - val accounts = publicRepos.map(repo => - Account( - repo.owner.uid, - repo.owner.name, - EmailAddress(s"${repo.owner.name}@example.com"), - account.fullName, - validatedEmail = true, - None - ) + PropF.forAllF { (account: Account, repositories: NonEmptyList[VcsRepository]) => + val privateRepos = + repositories.toList.filter(_.isPrivate === true).map(_.copy(owner = account.toVcsRepositoryOwner)) + val publicRepos = repositories.toList.filter(_.isPrivate === false) + val vcsRepositories = privateRepos ::: publicRepos + val accounts = publicRepos.map(repo => + Account( + repo.owner.uid, + repo.owner.name, + EmailAddress(s"${repo.owner.name}@example.com"), + account.fullName, + validatedEmail = true, + None ) - val expectedRepoList = vcsRepositories - val dbConfig = configuration.database - val tx = Transactor.fromDriverManager[IO]( - driver = dbConfig.driver, - url = dbConfig.url, - user = dbConfig.user, - password = dbConfig.pass, - logHandler = None + ) + val expectedRepoList = vcsRepositories + val dbConfig = configuration.database + val tx = Transactor.fromDriverManager[IO]( + driver = dbConfig.driver, + url = dbConfig.url, + user = dbConfig.user, + password = dbConfig.pass, + logHandler = None + ) + val repo = new DoobieVcsMetadataRepository[IO](tx) + val test = for { + _ <- createAccount(account, PasswordHash("I am not a password hash!"), None, None) + _ <- accounts.traverse(account => + createAccount(account, PasswordHash("I am not a password hash!"), None, None) + ) + written <- vcsRepositories.traverse(vcsRepository => repo.createVcsRepository(vcsRepository)) + foundRepos <- repo.listAllRepositories(account.some)(NameDescending).compile.toList + } yield (written, foundRepos) + test.start.flatMap(_.joinWithNever).map { result => + val (written, foundRepos) = result + assert( + written.filter(_ === 1).size === written.size, + "Not all test repository data was written to database!" ) - val repo = new DoobieVcsMetadataRepository[IO](tx) - val test = for { - _ <- createAccount(account, PasswordHash("I am not a password hash!"), None, None) - _ <- accounts.traverse(account => - createAccount(account, PasswordHash("I am not a password hash!"), None, None) - ) - written <- vcsRepositories.traverse(vcsRepository => repo.createVcsRepository(vcsRepository)) - foundRepos <- repo.listAllRepositories(account.some)(NameDescending).compile.toList - } yield (written, foundRepos) - test.map { result => - val (written, foundRepos) = result - assert( - written.filter(_ === 1).size === written.size, - "Not all test repository data was written to database!" - ) - assertEquals(foundRepos.size, expectedRepoList.size) - } - - case _ => fail("Could not generate data samples!") + assertEquals(foundRepos.size, expectedRepoList.size) + } } } test("listRepositories must return only public repositories for guest users".tag(NeedsDatabase)) { - (genValidAccount.sample, genValidVcsRepositories.sample) match { - case (Some(account), Some(repositories)) => - val vcsRepositories = repositories.map(_.copy(owner = account.toVcsRepositoryOwner)) - val expectedRepoList = vcsRepositories.filter(_.isPrivate === false).sortBy(_.name) - val dbConfig = configuration.database - val tx = Transactor.fromDriverManager[IO]( - driver = dbConfig.driver, - url = dbConfig.url, - user = dbConfig.user, - password = dbConfig.pass, - logHandler = None - ) - val repo = new DoobieVcsMetadataRepository[IO](tx) - val test = for { - _ <- createAccount(account, PasswordHash("I am not a password hash!"), None, None) - written <- vcsRepositories.traverse(vcsRepository => repo.createVcsRepository(vcsRepository)) - foundRepos <- repo.listRepositories(None)(account.toVcsRepositoryOwner).compile.toList - } yield (written, foundRepos) - test.map { result => - val (written, foundRepos) = result - assert( - written.filter(_ === 1).size === written.size, - "Not all test repository data was written to database!" - ) - assertEquals(foundRepos.size, expectedRepoList.size) - // We sort again because database sorting might differ slightly from code sorting. - assertEquals(foundRepos.sortBy(_.name), expectedRepoList) - } - case _ => fail("Could not generate data samples!") + PropF.forAllF { (account: Account, repositories: NonEmptyList[VcsRepository]) => + val vcsRepositories = repositories.toList.map(_.copy(owner = account.toVcsRepositoryOwner)) + val expectedRepoList = vcsRepositories.filter(_.isPrivate === false).sortBy(_.name) + val dbConfig = configuration.database + val tx = Transactor.fromDriverManager[IO]( + driver = dbConfig.driver, + url = dbConfig.url, + user = dbConfig.user, + password = dbConfig.pass, + logHandler = None + ) + val repo = new DoobieVcsMetadataRepository[IO](tx) + val test = for { + _ <- createAccount(account, PasswordHash("I am not a password hash!"), None, None) + written <- vcsRepositories.traverse(vcsRepository => repo.createVcsRepository(vcsRepository)) + foundRepos <- repo.listRepositories(None)(account.toVcsRepositoryOwner).compile.toList + } yield (written, foundRepos) + test.start.flatMap(_.joinWithNever).map { result => + val (written, foundRepos) = result + assert( + written.filter(_ === 1).size === written.size, + "Not all test repository data was written to database!" + ) + assertEquals(foundRepos.size, expectedRepoList.size) + // We sort again because database sorting might differ slightly from code sorting. + assertEquals(foundRepos.sortBy(_.name), expectedRepoList) + } } } test("listRepositories must return all repositories for the owner".tag(NeedsDatabase)) { - (genValidAccount.sample, genValidVcsRepositories.sample) match { - case (Some(account), Some(repositories)) => - val vcsRepositories = repositories.map(_.copy(owner = account.toVcsRepositoryOwner)) - val expectedRepoList = vcsRepositories.sortBy(_.name) - val dbConfig = configuration.database - val tx = Transactor.fromDriverManager[IO]( - driver = dbConfig.driver, - url = dbConfig.url, - user = dbConfig.user, - password = dbConfig.pass, - logHandler = None - ) - val repo = new DoobieVcsMetadataRepository[IO](tx) - val test = for { - _ <- createAccount(account, PasswordHash("I am not a password hash!"), None, None) - written <- vcsRepositories.traverse(vcsRepository => repo.createVcsRepository(vcsRepository)) - foundRepos <- repo.listRepositories(account.some)(account.toVcsRepositoryOwner).compile.toList - } yield (written, foundRepos) - test.map { result => - val (written, foundRepos) = result - assert( - written.filter(_ === 1).size === written.size, - "Not all test repository data was written to database!" - ) - assertEquals(foundRepos.size, expectedRepoList.size) - // We sort again because database sorting might differ slightly from code sorting. - assertEquals(foundRepos.sortBy(_.name), expectedRepoList) - } - case _ => fail("Could not generate data samples!") + PropF.forAllF { (account: Account, repositories: NonEmptyList[VcsRepository]) => + val vcsRepositories = repositories.toList.map(_.copy(owner = account.toVcsRepositoryOwner)) + val expectedRepoList = vcsRepositories.sortBy(_.name) + val dbConfig = configuration.database + val tx = Transactor.fromDriverManager[IO]( + driver = dbConfig.driver, + url = dbConfig.url, + user = dbConfig.user, + password = dbConfig.pass, + logHandler = None + ) + val repo = new DoobieVcsMetadataRepository[IO](tx) + val test = for { + _ <- createAccount(account, PasswordHash("I am not a password hash!"), None, None) + written <- vcsRepositories.traverse(vcsRepository => repo.createVcsRepository(vcsRepository)) + foundRepos <- repo.listRepositories(account.some)(account.toVcsRepositoryOwner).compile.toList + } yield (written, foundRepos) + test.start.flatMap(_.joinWithNever).map { result => + val (written, foundRepos) = result + assert( + written.filter(_ === 1).size === written.size, + "Not all test repository data was written to database!" + ) + assertEquals(foundRepos.size, expectedRepoList.size) + // We sort again because database sorting might differ slightly from code sorting. + assertEquals(foundRepos.sortBy(_.name), expectedRepoList) + } } } test("listRepositories must return only public repositories for any user".tag(NeedsDatabase)) { - (genValidAccount.sample, genValidVcsRepositories.sample, genValidAccount.sample) match { - case (Some(account), Some(repositories), Some(otherAccount)) => - val vcsRepositories = repositories.map(_.copy(owner = account.toVcsRepositoryOwner)) - val expectedRepoList = vcsRepositories.filter(_.isPrivate === false).sortBy(_.name) - val dbConfig = configuration.database - val tx = Transactor.fromDriverManager[IO]( - driver = dbConfig.driver, - url = dbConfig.url, - user = dbConfig.user, - password = dbConfig.pass, - logHandler = None - ) - val repo = new DoobieVcsMetadataRepository[IO](tx) - val test = for { - _ <- createAccount(account, PasswordHash("I am not a password hash!"), None, None) - written <- vcsRepositories.traverse(vcsRepository => repo.createVcsRepository(vcsRepository)) - foundRepos <- repo.listRepositories(otherAccount.some)(account.toVcsRepositoryOwner).compile.toList - } yield (written, foundRepos) - test.map { result => - val (written, foundRepos) = result - assert( - written.filter(_ === 1).size === written.size, - "Not all test repository data was written to database!" - ) - assertEquals(foundRepos.size, expectedRepoList.size) - // We sort again because database sorting might differ slightly from code sorting. - assertEquals(foundRepos.sortBy(_.name), expectedRepoList) - } - case _ => fail("Could not generate data samples!") + PropF.forAllF { (account: Account, repositories: NonEmptyList[VcsRepository], otherAccount: Account) => + val vcsRepositories = repositories.toList.map(_.copy(owner = account.toVcsRepositoryOwner)) + val expectedRepoList = vcsRepositories.filter(_.isPrivate === false).sortBy(_.name) + val dbConfig = configuration.database + val tx = Transactor.fromDriverManager[IO]( + driver = dbConfig.driver, + url = dbConfig.url, + user = dbConfig.user, + password = dbConfig.pass, + logHandler = None + ) + val repo = new DoobieVcsMetadataRepository[IO](tx) + val test = for { + _ <- createAccount(account, PasswordHash("I am not a password hash!"), None, None) + written <- vcsRepositories.traverse(vcsRepository => repo.createVcsRepository(vcsRepository)) + foundRepos <- repo.listRepositories(otherAccount.some)(account.toVcsRepositoryOwner).compile.toList + } yield (written, foundRepos) + test.start.flatMap(_.joinWithNever).map { result => + val (written, foundRepos) = result + assert( + written.filter(_ === 1).size === written.size, + "Not all test repository data was written to database!" + ) + assertEquals(foundRepos.size, expectedRepoList.size) + // We sort again because database sorting might differ slightly from code sorting. + assertEquals(foundRepos.sortBy(_.name), expectedRepoList) + } } } @@ -738,43 +702,44 @@ } test("updateVcsRepository must update all columns correctly".tag(NeedsDatabase)) { - (genValidAccount.sample, genValidVcsRepositories.sample) match { - case (Some(account), Some(repository :: repositories)) => - val vcsRepositories = repository.copy(owner = account.toVcsRepositoryOwner) :: repositories.map( + PropF.forAllF { (account: Account, repositories: NonEmptyList[VcsRepository]) => + val repository = repositories.head + val vcsRepositories = repository.copy(owner = account.toVcsRepositoryOwner) :: repositories.toList + .drop(1) + .map( _.copy(owner = account.toVcsRepositoryOwner) ) - val updatedRepo = repository - .copy(owner = account.toVcsRepositoryOwner) - .copy( - isPrivate = !repository.isPrivate, - description = Option(VcsRepositoryDescription("I am a description...")), - website = Option(uri"https://updated.example.com") - ) - val dbConfig = configuration.database - val tx = Transactor.fromDriverManager[IO]( - driver = dbConfig.driver, - url = dbConfig.url, - user = dbConfig.user, - password = dbConfig.pass, - logHandler = None + val updatedRepo = repository + .copy(owner = account.toVcsRepositoryOwner) + .copy( + isPrivate = !repository.isPrivate, + description = Option(VcsRepositoryDescription("I am a description...")), + website = Option(uri"https://updated.example.com") ) - val repo = new DoobieVcsMetadataRepository[IO](tx) - val test = for { - _ <- createAccount(account, PasswordHash("I am not a password hash!"), None, None) - written <- vcsRepositories.traverse(vcsRepository => repo.createVcsRepository(vcsRepository)) - updated <- repo.updateVcsRepository(updatedRepo) - persisted <- repo.findVcsRepository(account.toVcsRepositoryOwner, repository.name) - } yield (written, updated, persisted) - test.map { result => - val (written, updated, persisted) = result - assert( - written.filter(_ === 1).size === written.size, - "Not all test repository data was written to database!" - ) - assert(updated === 1, "Repository was not updated in database!") - assert(persisted === Some(updatedRepo)) - } - case _ => fail("Could not generate data samples!") + val dbConfig = configuration.database + val tx = Transactor.fromDriverManager[IO]( + driver = dbConfig.driver, + url = dbConfig.url, + user = dbConfig.user, + password = dbConfig.pass, + logHandler = None + ) + val repo = new DoobieVcsMetadataRepository[IO](tx) + val test = for { + _ <- createAccount(account, PasswordHash("I am not a password hash!"), None, None) + written <- vcsRepositories.traverse(vcsRepository => repo.createVcsRepository(vcsRepository)) + updated <- repo.updateVcsRepository(updatedRepo) + persisted <- repo.findVcsRepository(account.toVcsRepositoryOwner, repository.name) + } yield (written, updated, persisted) + test.start.flatMap(_.joinWithNever).map { result => + val (written, updated, persisted) = result + assert( + written.filter(_ === 1).size === written.size, + "Not all test repository data was written to database!" + ) + assert(updated === 1, "Repository was not updated in database!") + assert(persisted === Some(updatedRepo)) + } } } }