Persist two singleton entities in SQL tables (#860)

* Persist two singleton entities in SQL tables

A table might not be the best place to store singleton entities, but by
doing this we ensure we can easily inspect them later and use the same
sort of persistence logic for these that we do elsewhere.

ServerSecret is stored upon retrieval so that we make sure that the same
secret is used in both Datastore and SQL (we wouldn't want to change
it).

* Responses to CR

* Don't have a separate ID for the singleton entities

* Rename secret UUID

* Rename and regenerate
This commit is contained in:
gbrodman 2020-11-09 13:47:42 -05:00 committed by GitHub
parent cb764b5d30
commit 0c6363c04f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
15 changed files with 759 additions and 215 deletions

View file

@ -15,21 +15,25 @@
package google.registry.model.server;
import static com.google.common.truth.Truth.assertThat;
import static google.registry.model.common.CrossTldSingleton.SINGLETON_ID;
import static google.registry.model.common.EntityGroupRoot.getCrossTldKey;
import static google.registry.model.ofy.ObjectifyService.ofy;
import static google.registry.persistence.transaction.TransactionManagerFactory.jpaTm;
import com.googlecode.objectify.Key;
import google.registry.model.EntityTestCase;
import google.registry.model.ofy.RequestCapturingAsyncDatastoreService;
import google.registry.testing.AppEngineExtension;
import google.registry.persistence.VKey;
import java.util.UUID;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;
/** Unit tests for {@link ServerSecret}. */
public class ServerSecretTest {
public class ServerSecretTest extends EntityTestCase {
@RegisterExtension
public final AppEngineExtension appEngine =
AppEngineExtension.builder().withDatastoreAndCloudSql().build();
ServerSecretTest() {
super(JpaEntityCoverageCheck.ENABLED);
}
@BeforeEach
void beforeEach() {
@ -41,18 +45,20 @@ public class ServerSecretTest {
ServerSecret secret = ServerSecret.get();
assertThat(secret).isNotNull();
assertThat(ofy().load().entity(new ServerSecret()).now()).isEqualTo(secret);
assertThat(loadFromSql()).isEqualTo(secret);
}
@Test
void testGet_existingSecret_returned() {
ServerSecret secret = ServerSecret.create(123, 456);
ServerSecret secret = ServerSecret.create(new UUID(123, 456));
ofy().saveWithoutBackup().entity(secret).now();
assertThat(ServerSecret.get()).isEqualTo(secret);
assertThat(ofy().load().entity(new ServerSecret()).now()).isEqualTo(secret);
assertThat(loadFromSql()).isEqualTo(secret);
}
@Test
void testGet_cachedSecret_returnedWithoutDatastoreRead() {
void testGet_cachedSecret() {
int numInitialReads = RequestCapturingAsyncDatastoreService.getReads().size();
ServerSecret secret = ServerSecret.get();
int numReads = RequestCapturingAsyncDatastoreService.getReads().size();
@ -62,16 +68,28 @@ public class ServerSecretTest {
}
@Test
void testAsUuid() {
UUID uuid = ServerSecret.create(123, 456).asUuid();
assertThat(uuid.getMostSignificantBits()).isEqualTo(123);
assertThat(uuid.getLeastSignificantBits()).isEqualTo(456);
void testAsBytes() {
byte[] bytes = ServerSecret.create(new UUID(123, 0x456)).asBytes();
assertThat(bytes).isEqualTo(new byte[] {0, 0, 0, 0, 0, 0, 0, 123, 0, 0, 0, 0, 0, 0, 0x4, 0x56});
}
@Test
void testAsBytes() {
byte[] bytes = ServerSecret.create(123, 0x456).asBytes();
assertThat(bytes)
.isEqualTo(new byte[] {0, 0, 0, 0, 0, 0, 0, 123, 0, 0, 0, 0, 0, 0, 0x4, 0x56});
private static ServerSecret loadFromSql() {
return jpaTm()
.transact(
() ->
jpaTm()
.getEntityManager()
.createQuery("FROM ServerSecret", ServerSecret.class)
.setMaxResults(1)
.getResultStream()
.findFirst()
.get());
}
private static VKey<ServerSecret> createKey() {
return VKey.create(
ServerSecret.class,
SINGLETON_ID,
Key.create(getCrossTldKey(), ServerSecret.class, SINGLETON_ID));
}
}

View file

@ -15,22 +15,48 @@
package google.registry.model.tmch;
import static com.google.common.truth.Truth.assertThat;
import static google.registry.model.ofy.ObjectifyService.ofy;
import static google.registry.persistence.transaction.TransactionManagerFactory.jpaTm;
import google.registry.testing.AppEngineExtension;
import google.registry.model.EntityTestCase;
import java.util.Optional;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;
/** Unit tests for {@link TmchCrl}. */
public class TmchCrlTest {
public class TmchCrlTest extends EntityTestCase {
@RegisterExtension
public final AppEngineExtension appEngine =
AppEngineExtension.builder().withDatastoreAndCloudSql().build();
TmchCrlTest() {
super(JpaEntityCoverageCheck.ENABLED);
}
@Test
void testSuccess() {
assertThat(TmchCrl.get()).isNull();
TmchCrl.set("lolcat", "http://lol.cat");
assertThat(TmchCrl.get().getCrl()).isEqualTo("lolcat");
assertThat(TmchCrl.get()).isEqualTo(Optional.empty());
TmchCrl.set("lolcat", "https://lol.cat");
assertThat(TmchCrl.get().get().getCrl()).isEqualTo("lolcat");
}
@Test
void testDualWrite() {
TmchCrl expected = new TmchCrl();
expected.crl = "lolcat";
expected.url = "https://lol.cat";
expected.updated = fakeClock.nowUtc();
TmchCrl.set("lolcat", "https://lol.cat");
assertThat(ofy().load().entity(new TmchCrl()).now()).isEqualTo(expected);
assertThat(loadFromSql()).isEqualTo(expected);
}
private static TmchCrl loadFromSql() {
return jpaTm()
.transact(
() ->
jpaTm()
.getEntityManager()
.createQuery("FROM TmchCrl", TmchCrl.class)
.setMaxResults(1)
.getResultStream()
.findFirst()
.get());
}
}

View file

@ -43,12 +43,13 @@ import org.junit.jupiter.api.extension.RegisterExtension;
/** Unit tests for {@link RequestAuthenticator}. */
class RequestAuthenticatorTest {
@RegisterExtension final AppEngineExtension appEngine = AppEngineExtension.builder().build();
@RegisterExtension
final AppEngineExtension appEngine =
AppEngineExtension.builder().withDatastoreAndCloudSql().build();
private static final AuthSettings AUTH_NONE = AuthSettings.create(
ImmutableList.of(AuthMethod.INTERNAL),
AuthLevel.NONE,
UserPolicy.IGNORED);
private static final AuthSettings AUTH_NONE =
AuthSettings.create(
ImmutableList.of(AuthMethod.INTERNAL), AuthLevel.NONE, UserPolicy.IGNORED);
private static final AuthSettings AUTH_INTERNAL_OR_ADMIN = AuthSettings.create(
ImmutableList.of(AuthMethod.INTERNAL),

View file

@ -30,8 +30,10 @@ import google.registry.model.registry.RegistryTest;
import google.registry.model.registry.label.ReservedListSqlDaoTest;
import google.registry.model.reporting.Spec11ThreatMatchTest;
import google.registry.model.server.KmsSecretRevisionSqlDaoTest;
import google.registry.model.server.ServerSecretTest;
import google.registry.model.smd.SignedMarkRevocationListDaoTest;
import google.registry.model.tmch.ClaimsListDaoTest;
import google.registry.model.tmch.TmchCrlTest;
import google.registry.persistence.transaction.JpaEntityCoverageExtension;
import google.registry.persistence.transaction.JpaTestRules.JpaIntegrationWithCoverageExtension;
import google.registry.schema.cursor.CursorDaoTest;
@ -95,8 +97,10 @@ import org.junit.runner.RunWith;
RegistryTest.class,
ReservedListSqlDaoTest.class,
RegistryLockDaoTest.class,
ServerSecretTest.class,
SignedMarkRevocationListDaoTest.class,
Spec11ThreatMatchTest.class,
TmchCrlTest.class,
// AfterSuiteTest must be the last entry. See class javadoc for details.
AfterSuiteTest.class
})