/*
* Copyright 2011 yingxinwu.g@gmail.com
*
* 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 xink.vpn.test;
import static xink.vpn.Constants.*;
import static xink.vpn.KeepAlive.*;
import java.util.ArrayList;
import java.util.List;
import xink.vpn.VpnProfileRepository;
import xink.vpn.test.helper.RepositoryHelper;
import xink.vpn.wrapper.VpnProfile;
import xink.vpn.wrapper.VpnState;
import android.content.Intent;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
import android.test.AndroidTestCase;
import android.util.Log;
public class KeepAliveTest extends AndroidTestCase {
private RepositoryHelper helper;
private VpnProfileRepository repository;
private String activeVpnName = "pptp";
private VpnProfile activeProfile;
private SharedPreferences prefs;
@Override
protected void setUp() throws Exception {
super.setUp();
helper = new RepositoryHelper(mContext);
helper.clearRepository();
helper.populateRepository();
repository = VpnProfileRepository.getInstance(mContext);
activeProfile = repository.getProfileByName(activeVpnName);
assertNotNull(activeProfile);
repository.setActiveProfile(activeProfile);
prefs = PreferenceManager.getDefaultSharedPreferences(mContext);
}
@Override
protected void tearDown() throws Exception {
helper.clearRepository();
super.tearDown();
}
public void testVpnConnectted() throws Exception {
prefs.edit().putBoolean(PREF_ENABLED, true).putString(PREF_HEARTBEAT_PERIOD, "TEST_5_SEC").commit();
sendConnBroadcast(VpnState.CONNECTED);
Thread.sleep(60000); // wait at least 5 heartbeat periods
List<Thread> threads = findThreads(".*HeartbeatTimer.*");
Log.i("xink.test", threads.toString());
assertEquals("has only one timer", 1, threads.size());
}
public void testKeepAliveDisabled() throws Exception {
prefs.edit().putBoolean(PREF_ENABLED, false).putString(PREF_HEARTBEAT_PERIOD, "TEST_5_SEC").commit();
sendConnBroadcast(VpnState.CONNECTED);
Thread.sleep(11000);
List<Thread> threads = findThreads(".*HeartbeatTimer.*");
Log.i("xink.test", threads.toString());
assertEquals("has only one timer", 1, threads.size());
}
public void testVpnConnBroken() throws Exception {
sendConnBroadcast(VpnState.IDLE);
Thread.sleep(1000);
List<Thread> threads = findThreads(".*HeartbeatTimer.*");
Log.i("xink.test", threads.toString());
assertEquals("has only one timer", 1, threads.size());
}
private void sendConnBroadcast(final VpnState state) {
Intent intent = new Intent(ACTION_VPN_CONNECTIVITY);
intent.putExtra(BROADCAST_PROFILE_NAME, activeVpnName);
intent.putExtra(BROADCAST_CONNECTION_STATE, state);
mContext.sendBroadcast(intent);
}
private static List<Thread> findThreads(final String pattern) {
Thread[] allThreads = getAllThreads();
ArrayList<Thread> result = new ArrayList<Thread>(allThreads.length);
for (Thread thread : allThreads) {
if (thread == null) {
continue;
}
String name = thread.getName();
if (name.matches(pattern)) {
result.add(thread);
}
}
return result;
}
private static Thread[] getAllThreads() {
ThreadGroup rootGroup = Thread.currentThread().getThreadGroup();
ThreadGroup parentGroup;
while ((parentGroup = rootGroup.getParent()) != null) {
rootGroup = parentGroup;
}
Thread[] threads = new Thread[rootGroup.activeCount()];
while (rootGroup.enumerate(threads, true) == threads.length) {
threads = new Thread[threads.length * 2];
}
return threads;
}
}