forked from TEAMMATES/teammates
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[TEAMMATES#12048] v9: Skeleton implementation (TEAMMATES#12056)
- Loading branch information
1 parent
9c46277
commit 522e93a
Showing
42 changed files
with
1,949 additions
and
41 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
package teammates.it.storage.sqlapi; | ||
|
||
import org.testng.annotations.Test; | ||
|
||
import teammates.common.exception.EntityAlreadyExistsException; | ||
import teammates.common.exception.EntityDoesNotExistException; | ||
import teammates.it.test.BaseTestCaseWithSqlDatabaseAccess; | ||
import teammates.storage.sqlapi.CoursesDb; | ||
import teammates.storage.sqlentity.Course; | ||
|
||
/** | ||
* SUT: {@link CoursesDb}. | ||
*/ | ||
public class CoursesDbIT extends BaseTestCaseWithSqlDatabaseAccess { | ||
|
||
private final CoursesDb coursesDb = CoursesDb.inst(); | ||
|
||
@Test | ||
public void testCreateCourse() throws Exception { | ||
______TS("Create course, does not exists, succeeds"); | ||
|
||
Course course = new Course.CourseBuilder("course-id") | ||
.withName("course-name") | ||
.withInstitute("teammates") | ||
.build(); | ||
|
||
coursesDb.createCourse(course); | ||
|
||
Course actualCourse = coursesDb.getCourse("course-id"); | ||
verifyEquals(course, actualCourse); | ||
|
||
______TS("Create course, already exists, execption thrown"); | ||
|
||
Course identicalCourse = new Course.CourseBuilder("course-id") | ||
.withName("course-name") | ||
.withInstitute("teammates") | ||
.build(); | ||
assertNotSame(course, identicalCourse); | ||
|
||
assertThrows(EntityAlreadyExistsException.class, () -> coursesDb.createCourse(identicalCourse)); | ||
} | ||
|
||
@Test | ||
public void testUpdateCourse() throws Exception { | ||
______TS("Update course, does not exists, exception thrown"); | ||
|
||
Course course = new Course.CourseBuilder("course-id") | ||
.withName("course-name") | ||
.withInstitute("teammates") | ||
.build(); | ||
|
||
assertThrows(EntityDoesNotExistException.class, () -> coursesDb.updateCourse(course)); | ||
|
||
______TS("Update course, already exists, update successful"); | ||
|
||
coursesDb.createCourse(course); | ||
course.setName("new course name"); | ||
|
||
coursesDb.updateCourse(course); | ||
Course actual = coursesDb.getCourse("course-id"); | ||
verifyEquals(course, actual); | ||
|
||
______TS("Update detached course, already exists, update successful"); | ||
|
||
// same id, different name | ||
Course detachedCourse = new Course.CourseBuilder("course-id") | ||
.withName("course") | ||
.withInstitute("teammates") | ||
.build(); | ||
|
||
coursesDb.updateCourse(detachedCourse); | ||
verifyEquals(course, detachedCourse); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
/** | ||
* Contains test cases for {@link teammates.storage.search} package. | ||
*/ | ||
package teammates.it.storage.sqlapi; |
89 changes: 89 additions & 0 deletions
89
src/it/java/teammates/it/test/BaseTestCaseWithSqlDatabaseAccess.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
package teammates.it.test; | ||
|
||
import org.testcontainers.containers.PostgreSQLContainer; | ||
import org.testng.annotations.AfterMethod; | ||
import org.testng.annotations.AfterSuite; | ||
import org.testng.annotations.BeforeMethod; | ||
import org.testng.annotations.BeforeSuite; | ||
import org.testng.annotations.Test; | ||
|
||
import teammates.common.util.HibernateUtil; | ||
import teammates.common.util.JsonUtils; | ||
import teammates.sqllogic.api.Logic; | ||
import teammates.sqllogic.core.LogicStarter; | ||
import teammates.storage.sqlentity.BaseEntity; | ||
import teammates.storage.sqlentity.Course; | ||
import teammates.test.BaseTestCase; | ||
|
||
/** | ||
* Base test case for tests that access the database. | ||
*/ | ||
@Test(singleThreaded = true) | ||
public class BaseTestCaseWithSqlDatabaseAccess extends BaseTestCase { | ||
/** | ||
* Test container. | ||
*/ | ||
protected static final PostgreSQLContainer<?> PGSQL = new PostgreSQLContainer<>("postgres:15.1-alpine"); | ||
|
||
private final Logic logic = Logic.inst(); | ||
|
||
@BeforeSuite | ||
public static void setUpClass() throws Exception { | ||
PGSQL.start(); | ||
DbMigrationUtil.resetDb(PGSQL.getJdbcUrl(), PGSQL.getUsername(), PGSQL.getPassword()); | ||
HibernateUtil.buildSessionFactory(PGSQL.getJdbcUrl(), PGSQL.getUsername(), PGSQL.getPassword()); | ||
|
||
LogicStarter.initializeDependencies(); | ||
} | ||
|
||
@AfterSuite | ||
public static void tearDownClass() throws Exception { | ||
PGSQL.close(); | ||
} | ||
|
||
@BeforeMethod | ||
public void setUp() throws Exception { | ||
HibernateUtil.getSessionFactory().getCurrentSession().getTransaction().begin(); | ||
DbMigrationUtil.resetDb(PGSQL.getJdbcUrl(), PGSQL.getUsername(), PGSQL.getPassword()); | ||
} | ||
|
||
@AfterMethod | ||
public void tearDown() { | ||
HibernateUtil.getSessionFactory().getCurrentSession().getTransaction().commit(); | ||
} | ||
|
||
/** | ||
* Verifies that two entities are equal. | ||
*/ | ||
protected void verifyEquals(BaseEntity expected, BaseEntity actual) { | ||
if (expected instanceof Course) { | ||
Course expectedCourse = (Course) expected; | ||
Course actualCourse = (Course) actual; | ||
equalizeIrrelevantData(expectedCourse, actualCourse); | ||
assertEquals(JsonUtils.toJson(expectedCourse), JsonUtils.toJson(actualCourse)); | ||
} | ||
} | ||
|
||
/** | ||
* Verifies that the given entity is present in the database. | ||
*/ | ||
protected void verifyPresentInDatabase(BaseEntity expected) { | ||
BaseEntity actual = getEntity(expected); | ||
verifyEquals(expected, actual); | ||
} | ||
|
||
private BaseEntity getEntity(BaseEntity entity) { | ||
if (entity instanceof Course) { | ||
return logic.getCourse(((Course) entity).getId()); | ||
} else { | ||
throw new RuntimeException("Unknown entity type!"); | ||
} | ||
} | ||
|
||
private void equalizeIrrelevantData(Course expected, Course actual) { | ||
// Ignore time field as it is stamped at the time of creation in testing | ||
expected.setCreatedAt(actual.getCreatedAt()); | ||
expected.setUpdatedAt(actual.getUpdatedAt()); | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
package teammates.it.test; | ||
|
||
import java.io.File; | ||
import java.sql.Connection; | ||
import java.sql.DriverManager; | ||
import java.util.HashMap; | ||
import java.util.Map; | ||
|
||
import liquibase.Liquibase; | ||
import liquibase.Scope; | ||
import liquibase.database.Database; | ||
import liquibase.database.DatabaseFactory; | ||
import liquibase.database.jvm.JdbcConnection; | ||
import liquibase.resource.DirectoryResourceAccessor; | ||
|
||
/** | ||
* Utility class with methods to apply sql migrations in tests. | ||
*/ | ||
public final class DbMigrationUtil { | ||
|
||
private DbMigrationUtil() { | ||
// prevent instantiation | ||
} | ||
|
||
/** | ||
* Drop all tables and re-apply migrations. | ||
*/ | ||
public static void resetDb(String dbUrl, String username, String password) throws Exception { | ||
Map<String, Object> config = new HashMap<>(); | ||
File file = new File(System.getProperty("user.dir")); | ||
|
||
Scope.child(config, () -> { | ||
Connection conn = DriverManager.getConnection(dbUrl, username, password); | ||
Database database = DatabaseFactory.getInstance().findCorrectDatabaseImplementation(new JdbcConnection(conn)); | ||
try (Liquibase liquibase = new Liquibase("src/main/resources/db/changelog/db.changelog-root.xml", | ||
new DirectoryResourceAccessor(file), database)) { | ||
liquibase.dropAll(); | ||
liquibase.update(); | ||
} | ||
conn.close(); | ||
}); | ||
} | ||
} |
Oops, something went wrong.