Skip to content

Commit

Permalink
More firetactoe tests. Enforce login in web.xml
Browse files Browse the repository at this point in the history
  • Loading branch information
Jerjou Cheng committed Oct 20, 2016
1 parent a905ee8 commit b3fed9c
Show file tree
Hide file tree
Showing 9 changed files with 483 additions and 43 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ public void doPost(HttpServletRequest request, HttpServletResponse response)
UserService userService = UserServiceFactory.getUserService();
String currentUserId = userService.getCurrentUser().getUserId();

// TODO(you): In practice, first validate that the user has permission to delete the Game
game.deleteChannel(currentUserId);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ public void doPost(HttpServletRequest request, HttpServletResponse response)

int cell = new Integer(request.getParameter("cell"));
if (!game.makeMove(cell, currentUserId)) {
response.setStatus(HttpServletResponse.SC_FORBIDDEN);
response.sendError(HttpServletResponse.SC_FORBIDDEN);
} else {
ofy.save().entity(game).now();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@

package com.example.appengine.firetactoe;

import com.googlecode.objectify.NotFoundException;
import com.googlecode.objectify.Objectify;
import com.googlecode.objectify.ObjectifyService;

Expand All @@ -32,19 +31,10 @@ public class OpenedServlet extends HttpServlet {
@Override
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws IOException {
// TODO(you): In practice, you should validate the user has permission to post to the given Game
String gameId = request.getParameter("gameKey");
Objectify ofy = ObjectifyService.ofy();
try {
Game game = ofy.load().type(Game.class).id(gameId).safe();
if (gameId != null && request.getUserPrincipal() != null) {
game.sendUpdateToClients();
response.setContentType("text/plain");
response.getWriter().println("ok");
} else {
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
}
} catch (NotFoundException e) {
response.setStatus(HttpServletResponse.SC_NOT_FOUND);
}
Game game = ofy.load().type(Game.class).id(gameId).safe();
game.sendUpdateToClients();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@

package com.example.appengine.firetactoe;

import com.google.appengine.api.users.UserService;
import com.google.appengine.api.users.UserServiceFactory;
import com.google.gson.Gson;
import com.googlecode.objectify.Objectify;
Expand Down Expand Up @@ -60,18 +59,12 @@ private String getGameUriWithGameParam(HttpServletRequest request, String gameKe
@Override
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
final UserService userService = UserServiceFactory.getUserService();
String gameKey = request.getParameter("gameKey");
if (userService.getCurrentUser() == null) {
response.getWriter().println("<p>Please <a href=\"" + userService.createLoginURL(
getGameUriWithGameParam(request, gameKey)) + "\">sign in</a>.</p>");
return;
}

// 1. Create or fetch a Game object from the datastore
Objectify ofy = ObjectifyService.ofy();
Game game = null;
String userId = userService.getCurrentUser().getUserId();
String userId = UserServiceFactory.getUserService().getCurrentUser().getUserId();
if (gameKey != null) {
game = ofy.load().type(Game.class).id(gameKey).now();
if (null == game) {
Expand Down
9 changes: 9 additions & 0 deletions appengine/firebase-tictactoe/src/main/webapp/WEB-INF/web.xml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,15 @@ http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5">
<welcome-file-list>
<welcome-file>index</welcome-file>
</welcome-file-list>
<security-constraint>
<web-resource-collection>
<web-resource-name>entire-app</web-resource-name>
<url-pattern>/*</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>*</role-name>
</auth-constraint>
</security-constraint>
<servlet>
<servlet-name>TicTacToeServlet</servlet-name>
<servlet-class>com.example.appengine.firetactoe.TicTacToeServlet</servlet-class>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
/*
* 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.example.appengine.firetactoe;

import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.fail;
import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import com.google.api.client.http.LowLevelHttpRequest;
import com.google.api.client.http.LowLevelHttpResponse;
import com.google.api.client.testing.http.MockHttpTransport;
import com.google.api.client.testing.http.MockLowLevelHttpRequest;
import com.google.api.client.testing.http.MockLowLevelHttpResponse;
import com.google.appengine.tools.development.testing.LocalDatastoreServiceTestConfig;
import com.google.appengine.tools.development.testing.LocalServiceTestHelper;
import com.google.appengine.tools.development.testing.LocalURLFetchServiceTestConfig;
import com.google.appengine.tools.development.testing.LocalUserServiceTestConfig;
import com.google.common.collect.ImmutableMap;
import com.googlecode.objectify.Objectify;
import com.googlecode.objectify.ObjectifyFactory;
import com.googlecode.objectify.ObjectifyService;
import com.googlecode.objectify.util.Closeable;
import org.junit.After;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
import org.mockito.Matchers;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.util.HashMap;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
* Unit tests for {@link DeleteServlet}.
*/
@RunWith(JUnit4.class)
public class DeleteServletTest {
private static final String USER_EMAIL = "[email protected]";
private static final String USER_ID = "whiskytangofoxtrot";
private static final String FIREBASE_DB_URL = "http://firebase.com/dburl";

private final LocalServiceTestHelper helper =
new LocalServiceTestHelper(
// Set no eventual consistency, that way queries return all results.
// http://g.co/cloud/appengine/docs/java/tools/localunittesting#Java_Writing_High_Replication_Datastore_tests
new LocalDatastoreServiceTestConfig().setDefaultHighRepJobPolicyUnappliedJobPercentage(0),
new LocalUserServiceTestConfig(),
new LocalURLFetchServiceTestConfig()
)
.setEnvEmail(USER_EMAIL)
.setEnvAuthDomain("gmail.com")
.setEnvAttributes(new HashMap(
ImmutableMap.of("com.google.appengine.api.users.UserService.user_id_key", USER_ID)));

@Mock private HttpServletRequest mockRequest;
@Mock private HttpServletResponse mockResponse;
protected Closeable dbSession;

private DeleteServlet servletUnderTest;

@BeforeClass
public static void setUpBeforeClass() {
// Reset the Factory so that all translators work properly.
ObjectifyService.setFactory(new ObjectifyFactory());
ObjectifyService.register(Game.class);
// Mock out the firebase config
FirebaseChannel.firebaseConfigStream = new ByteArrayInputStream(
String.format("databaseURL: \"%s\"", FIREBASE_DB_URL).getBytes());
}

@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
helper.setUp();
dbSession = ObjectifyService.begin();

servletUnderTest = new DeleteServlet();

helper.setEnvIsLoggedIn(true);
// Make sure there are no firebase requests if we don't expect it
FirebaseChannel.getInstance().httpTransport = null;
}

@After
public void tearDown() {
dbSession.close();
helper.tearDown();
}

@Test
public void doPost_noGameKey() throws Exception {
try {
servletUnderTest.doPost(mockRequest, mockResponse);
fail("Should not succeed with no gameKey specified.");
} catch (IllegalArgumentException e) {
assertThat(e.getMessage()).startsWith("id 'null'");
}
}

@Test
public void doPost_deleteGame() throws Exception {
// Insert a game
Objectify ofy = ObjectifyService.ofy();
Game game = new Game(USER_ID, "my-opponent", " ", true);
ofy.save().entity(game).now();
String gameKey = game.getId();
when(mockRequest.getParameter("gameKey")).thenReturn(gameKey);

// Mock out the firebase response. See
// http://g.co/dv/api-client-library/java/google-http-java-client/unit-testing
MockHttpTransport mockHttpTransport = spy(new MockHttpTransport() {
@Override
public LowLevelHttpRequest buildRequest(String method, String url) throws IOException {
return new MockLowLevelHttpRequest() {
@Override
public LowLevelHttpResponse execute() throws IOException {
MockLowLevelHttpResponse response = new MockLowLevelHttpResponse();
response.setStatusCode(200);
return response;
}
};
}
});
FirebaseChannel.getInstance().httpTransport = mockHttpTransport;

servletUnderTest.doPost(mockRequest, mockResponse);

verify(mockHttpTransport, times(1)).buildRequest(
eq("DELETE"), Matchers.matches(FIREBASE_DB_URL + "/channels/[\\w-]+.json$"));
}
}
Loading

0 comments on commit b3fed9c

Please sign in to comment.