package gaej2011.controller;
import static org.hamcrest.CoreMatchers.*;
import static org.junit.Assert.*;
import gaej2011.meta.MinutesChannelMeta;
import gaej2011.model.MinutesChannel;
import gaej2011.service.MemoService;
import gaej2011.service.MinutesService;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Future;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletResponse;
import org.junit.Test;
import org.slim3.datastore.Datastore;
import org.slim3.tester.ControllerTestCase;
import com.google.appengine.api.channel.ChannelServicePb;
import com.google.appengine.api.datastore.Key;
import com.google.apphosting.api.ApiProxy;
import com.google.apphosting.api.ApiProxy.ApiConfig;
import com.google.apphosting.api.ApiProxy.ApiProxyException;
import com.google.apphosting.api.ApiProxy.Delegate;
import com.google.apphosting.api.ApiProxy.Environment;
import com.google.apphosting.api.ApiProxy.LogRecord;
public class ChannelControllerTest extends ControllerTestCase {
static final String PATH = "/Channel";
@Test
public void 新しいチャンネルを作成できる() throws NullPointerException,
IllegalArgumentException, IOException, ServletException {
// テスト用の議事録
Key testMinutesKey = MinutesService.put(" テスト用議事録1");
tester.request.setMethod("GET");
tester.param("minutes", Datastore.keyToString(testMinutesKey));
tester.start(PATH);
assertThat(
"ChannelController のインスタンスが使用される",
tester.getController(),
instanceOf(ChannelController.class));
assertThat(
" レスポンスコードが200",
tester.response.getStatus(),
is(HttpServletResponse.SC_OK));
MinutesChannel minutesChannel =
MinutesChannelMeta.get().jsonToModel(
tester.response.getOutputAsString());
assertThat(
"channel のtoken が返される",
minutesChannel.getToken(),
is(notNullValue()));
}
@Test
public void 接続済みのチャンネルにプッシュできる() {
// テスト用の議事録
Key testMinutesKey = MinutesService.put(" テスト用議事録1");
// テスト用の接続済みチャンネル1
MinutesChannel minutesChannel1 = new MinutesChannel();
minutesChannel1.setMinutesKey(testMinutesKey);
minutesChannel1.setToken("test-token1");
minutesChannel1.setKey(Datastore.createKey(
MinutesChannel.class,
"test-client-id1"));
Datastore.put(minutesChannel1);
// テスト用の接続済みチャンネル2
MinutesChannel minutesChannel2 = new MinutesChannel();
minutesChannel2.setMinutesKey(testMinutesKey);
minutesChannel2.setToken("test-token2");
minutesChannel2.setKey(Datastore.createKey(
MinutesChannel.class,
"test-client-id2"));
Datastore.put(minutesChannel2);
// 新たに投稿されてプッシュされるべき投稿
Key memoKey = MemoService.put(testMinutesKey, "test 投稿");
ChannelDelegate channelDelegate = new ChannelDelegate();
ApiProxy.setDelegate(channelDelegate);
try {
ChannelController.pushMemo(memoKey);
} finally {
ApiProxy.setDelegate(channelDelegate.parent);
}
assertThat(
" 接続済みのチャンネルにプッシュされる",
channelDelegate.sendMessageRequests.size(),
is(2));
assertThat(channelDelegate.sendMessageRequests
.get(0)
.getApplicationKey(), is("test-client-id1"));
assertThat(channelDelegate.sendMessageRequests
.get(1)
.getApplicationKey(), is("test-client-id2"));
}
@Test
public void 接続済みのチャンネルにプッシュできる_関係ないチャンネルにはプッシュされない() {
// テスト用の議事録
Key testMinutesKey = MinutesService.put(" テスト用議事録1");
// テスト用の接続済みチャンネル1
MinutesChannel minutesChannel1 = new MinutesChannel();
minutesChannel1.setMinutesKey(testMinutesKey);
minutesChannel1.setToken("test-token1");
minutesChannel1.setKey(Datastore.createKey(
MinutesChannel.class,
"test-client-id1"));
Datastore.put(minutesChannel1);
// 新たに投稿されてプッシュされるべき投稿
Key memoKey = MemoService.put(testMinutesKey, "test 投稿");
// テスト用の議事録2(プッシュとは関係ない議事録)
Key testMinutesKey2 = MinutesService.put(" テスト用議事録2");
// テスト用の接続済みチャンネル2(プッシュとは関係ないチャンネル)
MinutesChannel minutesChannel2 = new MinutesChannel();
minutesChannel2.setMinutesKey(testMinutesKey2);
minutesChannel2.setToken("test-token2");
minutesChannel2.setKey(Datastore.createKey(
MinutesChannel.class,
"test-client-id2"));
Datastore.put(minutesChannel2);
ChannelDelegate channelDelegate = new ChannelDelegate();
ApiProxy.setDelegate(channelDelegate);
try {
ChannelController.pushMemo(memoKey);
} finally {
ApiProxy.setDelegate(channelDelegate.parent);
}
assertThat(
" 接続済みのチャンネルにのみプッシュされる",
channelDelegate.sendMessageRequests.size(),
is(1));
assertThat(channelDelegate.sendMessageRequests
.get(0)
.getApplicationKey(), is("test-client-id1"));
}
static class ChannelDelegate implements Delegate<Environment> {
@SuppressWarnings("unchecked")
final Delegate<Environment> parent = ApiProxy.getDelegate();
public void flushLogs(Environment environment) {
parent.flushLogs(environment);
}
public List<Thread> getRequestThreads(Environment environment) {
return parent.getRequestThreads(environment);
}
public void log(Environment environment, LogRecord record) {
parent.log(environment, record);
}
public Future<byte[]> makeAsyncCall(Environment environment,
String packageName, String methodName, byte[] request,
ApiConfig apiConfig) {
inspectChennelService(packageName, methodName, request);
return parent.makeAsyncCall(
environment,
packageName,
methodName,
request,
apiConfig);
}
public byte[] makeSyncCall(Environment environment, String packageName,
String methodName, byte[] request) throws ApiProxyException {
inspectChennelService(packageName, methodName, request);
return parent.makeSyncCall(
environment,
packageName,
methodName,
request);
}
final List<ChannelServicePb.CreateChannelRequest> createChannelRequests =
new ArrayList<ChannelServicePb.CreateChannelRequest>();
final List<ChannelServicePb.SendMessageRequest> sendMessageRequests =
new ArrayList<ChannelServicePb.SendMessageRequest>();
void inspectChennelService(String packageName, String methodName,
byte[] request) {
if (packageName.equals("channel")
&& methodName.equals("CreateChannel")) {
ChannelServicePb.CreateChannelRequest requestPb =
new ChannelServicePb.CreateChannelRequest();
requestPb.mergeFrom(request);
createChannelRequests.add(requestPb);
} else if (packageName.equals("channel")
&& methodName.equals("SendChannelMessage")) {
ChannelServicePb.SendMessageRequest requestPb =
new ChannelServicePb.SendMessageRequest();
requestPb.mergeFrom(request);
sendMessageRequests.add(requestPb);
}
}
}
}