Skip to content

Commit

Permalink
Merge pull request #754 from mziccard/serialization-tests
Browse files Browse the repository at this point in the history
Create base class for serialization tests
  • Loading branch information
aozarov committed Mar 18, 2016
2 parents 872a1a4 + d629a30 commit 1a70376
Show file tree
Hide file tree
Showing 5 changed files with 254 additions and 10 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -276,8 +276,20 @@ private static class NoAuthCredentialsState
public AuthCredentials restore() {
return INSTANCE;
}

@Override
public int hashCode() {
return getClass().getName().hashCode();
}

@Override
public boolean equals(Object obj) {
return obj instanceof NoAuthCredentialsState;
}
}

private NoAuthCredentials() {}

@Override
public GoogleCredentials credentials() {
return null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,16 @@
*/
public class BaseServiceException extends RuntimeException {

private static final long serialVersionUID = 759921776378760835L;
public static final int UNKNOWN_CODE = 0;

private final int code;
private final boolean retryable;
private final String reason;
private final boolean idempotent;
private final String location;
private final String debugInfo;

protected static final class Error implements Serializable {

private static final long serialVersionUID = -4019600198652965721L;
Expand Down Expand Up @@ -79,16 +89,6 @@ public int hashCode() {
}
}

private static final long serialVersionUID = 759921776378760835L;
public static final int UNKNOWN_CODE = 0;

private final int code;
private final boolean retryable;
private final String reason;
private final boolean idempotent;
private final String location;
private final String debugInfo;

public BaseServiceException(IOException exception, boolean idempotent) {
super(message(exception), exception);
int code = UNKNOWN_CODE;
Expand Down Expand Up @@ -198,6 +198,31 @@ protected String debugInfo() {
return debugInfo;
}

@Override
public boolean equals(Object obj) {
if (obj == this) {
return true;
}
if (!(obj instanceof BaseServiceException)) {
return false;
}
BaseServiceException other = (BaseServiceException) obj;
return Objects.equals(getCause(), other.getCause())
&& Objects.equals(getMessage(), other.getMessage())
&& code == other.code
&& retryable == other.retryable
&& Objects.equals(reason, other.reason)
&& idempotent == other.idempotent
&& Objects.equals(location, other.location)
&& Objects.equals(debugInfo, other.debugInfo);
}

@Override
public int hashCode() {
return Objects.hash(getCause(), getMessage(), code, retryable, reason, idempotent, location,
debugInfo);
}

protected static String reason(GoogleJsonError error) {
if (error.getErrors() != null && !error.getErrors().isEmpty()) {
return error.getErrors().get(0).getReason();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@

import java.io.Serializable;
import java.lang.reflect.Method;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.Callable;

Expand Down Expand Up @@ -259,6 +260,26 @@ boolean shouldRetry(Exception ex) {
return retryResult == Interceptor.RetryResult.RETRY;
}

@Override
public int hashCode() {
return Objects.hash(interceptors, retriableExceptions, nonRetriableExceptions, retryInfo);
}

@Override
public boolean equals(Object obj) {
if (obj == this) {
return true;
}
if (!(obj instanceof ExceptionHandler)) {
return false;
}
ExceptionHandler other = (ExceptionHandler) obj;
return Objects.equals(interceptors, other.interceptors)
&& Objects.equals(retriableExceptions, other.retriableExceptions)
&& Objects.equals(nonRetriableExceptions, other.nonRetriableExceptions)
&& Objects.equals(retryInfo, other.retryInfo);
}

/**
* Returns an instance which retry any checked exception and abort on any runtime exception.
*/
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
/*
* Copyright 2016 Google Inc. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.google.gcloud;

import static com.google.common.base.MoreObjects.firstNonNull;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotSame;

import org.junit.Test;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;

/**
* Base class for serialization tests. To use this class in your tests override the
* {@code serializableObjects()} method to return all objects that must be serializable. Also
* override {@code restorableObjects()} method to return all restorable objects whose state must be
* tested for proper serialization. Both methods can return {@code null} if no such object needs to
* be tested.
*/
public abstract class BaseSerializationTest {

/**
* Returns all objects for which correct serialization must be tested.
*/
protected abstract Serializable[] serializableObjects();

/**
* Returns all restorable objects whose state must be tested for proper serialization.
*/
protected abstract Restorable<?>[] restorableObjects();

@Test
public void testSerializableObjects() throws Exception {
for (Serializable obj : firstNonNull(serializableObjects(), new Serializable[0])) {
Object copy = serializeAndDeserialize(obj);
assertEquals(obj, obj);
assertEquals(obj, copy);
assertEquals(obj.hashCode(), copy.hashCode());
assertEquals(obj.toString(), copy.toString());
assertNotSame(obj, copy);
assertEquals(copy, copy);
}
}

@Test
public void testRestorableObjects() throws Exception {
for (Restorable restorable : firstNonNull(restorableObjects(), new Restorable[0])) {
RestorableState<?> state = restorable.capture();
RestorableState<?> deserializedState = serializeAndDeserialize(state);
assertEquals(state, deserializedState);
assertEquals(state.hashCode(), deserializedState.hashCode());
assertEquals(state.toString(), deserializedState.toString());
}
}

@SuppressWarnings("unchecked")
public <T> T serializeAndDeserialize(T obj) throws IOException, ClassNotFoundException {
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
try (ObjectOutputStream output = new ObjectOutputStream(bytes)) {
output.writeObject(obj);
}
try (ObjectInputStream input =
new ObjectInputStream(new ByteArrayInputStream(bytes.toByteArray()))) {
return (T) input.readObject();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
/*
* Copyright 2016 Google Inc. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.google.gcloud;

import com.google.common.collect.ImmutableList;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.Serializable;

public class SerializationTest extends BaseSerializationTest {

private static class SomeIamPolicy extends IamPolicy<String> {

private static final long serialVersionUID = 271243551016958285L;

private static class Builder extends IamPolicy.Builder<String, Builder> {

@Override
public SomeIamPolicy build() {
return new SomeIamPolicy(this);
}
}

protected SomeIamPolicy(Builder builder) {
super(builder);
}

@Override
public Builder toBuilder() {
return new Builder();
}
}

private static final BaseServiceException BASE_SERVICE_EXCEPTION =
new BaseServiceException(42, "message", "reason", true);
private static final ExceptionHandler EXCEPTION_HANDLER = ExceptionHandler.defaultInstance();
private static final Identity IDENTITY = Identity.allAuthenticatedUsers();
private static final PageImpl<String> PAGE =
new PageImpl<>(null, "cursor", ImmutableList.of("string1", "string2"));
private static final RetryParams RETRY_PARAMS = RetryParams.defaultInstance();
private static final SomeIamPolicy SOME_IAM_POLICY = new SomeIamPolicy.Builder().build();
private static final String JSON_KEY = "{\n"
+ " \"private_key_id\": \"somekeyid\",\n"
+ " \"private_key\": \"-----BEGIN PRIVATE KEY-----\\nMIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggS"
+ "kAgEAAoIBAQC+K2hSuFpAdrJI\\nnCgcDz2M7t7bjdlsadsasad+fvRSW6TjNQZ3p5LLQY1kSZRqBqylRkzteMOyHg"
+ "aR\\n0Pmxh3ILCND5men43j3h4eDbrhQBuxfEMalkG92sL+PNQSETY2tnvXryOvmBRwa/\\nQP/9dJfIkIDJ9Fw9N4"
+ "Bhhhp6mCcRpdQjV38H7JsyJ7lih/oNjECgYAt\\nknddadwkwewcVxHFhcZJO+XWf6ofLUXpRwiTZakGMn8EE1uVa2"
+ "LgczOjwWHGi99MFjxSer5m9\\n1tCa3/KEGKiS/YL71JvjwX3mb+cewlkcmweBKZHM2JPTk0ZednFSpVZMtycjkbLa"
+ "\\ndYOS8V85AgMBewECggEBAKksaldajfDZDV6nGqbFjMiizAKJolr/M3OQw16K6o3/\\n0S31xIe3sSlgW0+UbYlF"
+ "4U8KifhManD1apVSC3csafaspP4RZUHFhtBywLO9pR5c\\nr6S5aLp+gPWFyIp1pfXbWGvc5VY/v9x7ya1VEa6rXvL"
+ "sKupSeWAW4tMj3eo/64ge\\nsdaceaLYw52KeBYiT6+vpsnYrEkAHO1fF/LavbLLOFJmFTMxmsNaG0tuiJHgjshB\\"
+ "n82DpMCbXG9YcCgI/DbzuIjsdj2JC1cascSP//3PmefWysucBQe7Jryb6NQtASmnv\\nCdDw/0jmZTEjpe4S1lxfHp"
+ "lAhHFtdgYTvyYtaLZiVVkCgYEA8eVpof2rceecw/I6\\n5ng1q3Hl2usdWV/4mZMvR0fOemacLLfocX6IYxT1zA1FF"
+ "JlbXSRsJMf/Qq39mOR2\\nSpW+hr4jCoHeRVYLgsbggtrevGmILAlNoqCMpGZ6vDmJpq6ECV9olliDvpPgWOP+\\nm"
+ "YPDreFBGxWvQrADNbRt2dmGsrsCgYEAyUHqB2wvJHFqdmeBsaacewzV8x9WgmeX\\ngUIi9REwXlGDW0Mz50dxpxcK"
+ "CAYn65+7TCnY5O/jmL0VRxU1J2mSWyWTo1C+17L0\\n3fUqjxL1pkefwecxwecvC+gFFYdJ4CQ/MHHXU81Lwl1iWdF"
+ "Cd2UoGddYaOF+KNeM\\nHC7cmqra+JsCgYEAlUNywzq8nUg7282E+uICfCB0LfwejuymR93CtsFgb7cRd6ak\\nECR"
+ "8FGfCpH8ruWJINllbQfcHVCX47ndLZwqv3oVFKh6pAS/vVI4dpOepP8++7y1u\\ncoOvtreXCX6XqfrWDtKIvv0vjl"
+ "HBhhhp6mCcRpdQjV38H7JsyJ7lih/oNjECgYAt\\nkndj5uNl5SiuVxHFhcZJO+XWf6ofLUregtevZakGMn8EE1uVa"
+ "2AY7eafmoU/nZPT\\n00YB0TBATdCbn/nBSuKDESkhSg9s2GEKQZG5hBmL5uCMfo09z3SfxZIhJdlerreP\\nJ7gSi"
+ "dI12N+EZxYd4xIJh/HFDgp7RRO87f+WJkofMQKBgGTnClK1VMaCRbJZPriw\\nEfeFCoOX75MxKwXs6xgrw4W//AYG"
+ "GUjDt83lD6AZP6tws7gJ2IwY/qP7+lyhjEqN\\nHtfPZRGFkGZsdaksdlaksd323423d+15/UvrlRSFPNj1tWQmNKk"
+ "XyRDW4IG1Oa2p\\nrALStNBx5Y9t0/LQnFI4w3aG\\n-----END PRIVATE KEY-----\\n\",\n"
+ " \"client_email\": \"someclientid@developer.gserviceaccount.com\",\n"
+ " \"client_id\": \"someclientid.apps.googleusercontent.com\",\n"
+ " \"type\": \"service_account\"\n"
+ "}";

@Override
protected Serializable[] serializableObjects() {
return new Serializable[]{BASE_SERVICE_EXCEPTION, EXCEPTION_HANDLER, IDENTITY, PAGE,
RETRY_PARAMS, SOME_IAM_POLICY};
}

@Override
protected Restorable<?>[] restorableObjects() {
try {
return new Restorable<?>[]{AuthCredentials.createForAppEngine(), AuthCredentials.noAuth(),
AuthCredentials.createForJson(new ByteArrayInputStream(JSON_KEY.getBytes()))};
} catch (IOException ex) {
// never reached
throw new RuntimeException(ex);
}
}
}

0 comments on commit 1a70376

Please sign in to comment.