/** * Copyright 2010 Google Inc. * * 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 org.waveprotocol.box.server.robots.operations; import static org.mockito.Matchers.any; import static org.mockito.Matchers.anyString; import static org.mockito.Matchers.eq; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyZeroInteractions; import static org.mockito.Mockito.when; import com.google.wave.api.InvalidRequestException; import com.google.wave.api.JsonRpcConstant.ParamsProperty; import com.google.wave.api.OperationRequest; import com.google.wave.api.OperationRequest.Parameter; import com.google.wave.api.ProtocolVersion; import com.google.wave.api.event.EventType; import com.google.wave.api.robot.Capability; import com.google.wave.api.robot.CapabilityFetchException; import junit.framework.TestCase; import org.waveprotocol.box.server.account.AccountData; import org.waveprotocol.box.server.account.RobotAccountData; import org.waveprotocol.box.server.account.RobotAccountDataImpl; import org.waveprotocol.box.server.persistence.AccountStore; import org.waveprotocol.box.server.robots.OperationContext; import org.waveprotocol.box.server.robots.RobotCapabilities; import org.waveprotocol.box.server.robots.passive.RobotConnector; import org.waveprotocol.wave.model.wave.ParticipantId; import java.util.Collections; import java.util.Map; public class NotifyOperationServiceTest extends TestCase { private static final Map<EventType, Capability> EMPTY_CAPABILITIES = Collections.<EventType, Capability> emptyMap(); private static final String OP_ID = "op1"; private static final ParticipantId ROBOT = ParticipantId.ofUnsafe("robot@example.com"); private static final String OLD_HASH = "oldHash"; private static final RobotCapabilities OLD_CAPABILITIES = new RobotCapabilities( EMPTY_CAPABILITIES, OLD_HASH, ProtocolVersion.V2_2); private static final RobotAccountData ROBOT_ACCOUNT = new RobotAccountDataImpl(ROBOT, "http://www.example.com", "fake", OLD_CAPABILITIES, true); private static final String NEW_HASH = "newHash"; private static final RobotCapabilities NEW_CAPABILITIES = new RobotCapabilities( EMPTY_CAPABILITIES, NEW_HASH, ProtocolVersion.V2_2); private static final RobotAccountData NEW_ROBOT_ACCOUNT = new RobotAccountDataImpl(ROBOT, "http://www.example.com", "fake", NEW_CAPABILITIES, true); private AccountStore accountStore; private RobotConnector connector; private NotifyOperationService operationService; private OperationContext context; @Override protected void setUp() throws Exception { accountStore = mock(AccountStore.class); connector = mock(RobotConnector.class); context = mock(OperationContext.class); operationService = new NotifyOperationService(accountStore, connector); when(accountStore.getAccount(ROBOT)).thenReturn(ROBOT_ACCOUNT); when(connector.fetchCapabilities(eq(ROBOT_ACCOUNT), anyString())).thenReturn(NEW_ROBOT_ACCOUNT); } public void testUpdateCapabilites() throws Exception { OperationRequest operation = new OperationRequest( "robot.notify", OP_ID, Parameter.of(ParamsProperty.CAPABILITIES_HASH, NEW_HASH)); operationService.execute(operation, context, ROBOT); verify(connector).fetchCapabilities(eq(ROBOT_ACCOUNT), anyString()); verify(accountStore).putAccount(NEW_ROBOT_ACCOUNT); } public void testDontUpdateIfHashesMatch() throws Exception { OperationRequest operation = new OperationRequest("robot.notify", OP_ID, Parameter.of(ParamsProperty.CAPABILITIES_HASH, OLD_HASH)); operationService.execute(operation, context, ROBOT); verifyZeroInteractions(connector); verify(accountStore, never()).putAccount(any(AccountData.class)); } public void testErrorOnFailingConnection() throws Exception { OperationRequest operation = new OperationRequest("robot.notify", OP_ID, Parameter.of(ParamsProperty.CAPABILITIES_HASH, NEW_HASH)); when(connector.fetchCapabilities(any(RobotAccountData.class), anyString())).thenThrow( new CapabilityFetchException("")); operationService.execute(operation, context, ROBOT); verify(accountStore, never()).putAccount(any(AccountData.class)); verify(context).constructErrorResponse(eq(operation), anyString()); } public void testExceptionOnUnknownAccount() throws Exception { OperationRequest operation = new OperationRequest("robot.notify", OP_ID, Parameter.of(ParamsProperty.CAPABILITIES_HASH, NEW_HASH)); when(accountStore.getAccount(ROBOT)).thenReturn(null); try { operationService.execute(operation, context, ROBOT); fail("Expected InvalidRequestException"); } catch (InvalidRequestException e) { // expected } verifyZeroInteractions(connector); verify(accountStore, never()).putAccount(any(AccountData.class)); } public void testExceptionOnMissingHash() throws Exception { OperationRequest operation = new OperationRequest("robot.notify", OP_ID); try { operationService.execute(operation, context, ROBOT); fail("Expected InvalidRequestException"); } catch (InvalidRequestException e) { // expected } verifyZeroInteractions(connector); verify(accountStore, never()).putAccount(any(AccountData.class)); } }