blob: f567ef6d5ded70891228caac085f7b81d093069a [file] [log] [blame]
/*
* Copyright (C) 2016 The Android Open Source Project
*
* 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.android.server.wifi;
import static com.android.server.wifi.WifiConfigStoreDataTest.assertConfigStoreDataEqual;
import static org.junit.Assert.*;
import static org.mockito.Mockito.*;
import android.app.test.TestAlarmManager;
import android.content.Context;
import android.net.wifi.WifiConfiguration;
import android.os.test.TestLooper;
import android.test.suitebuilder.annotation.SmallTest;
import com.android.server.wifi.WifiConfigStore.StoreFile;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import java.io.File;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
/**
* Unit tests for {@link com.android.server.wifi.WifiConfigStore}.
*/
@SmallTest
public class WifiConfigStoreTest {
// Test mocks
@Mock private Context mContext;
private TestAlarmManager mAlarmManager;
private TestLooper mLooper;
@Mock private Clock mClock;
private MockStoreFile mSharedStore;
private MockStoreFile mUserStore;
/**
* Test instance of WifiConfigStore.
*/
private WifiConfigStore mWifiConfigStore;
/**
* Setup mocks before the test starts.
*/
private void setupMocks() throws Exception {
MockitoAnnotations.initMocks(this);
mAlarmManager = new TestAlarmManager();
mLooper = new TestLooper();
when(mContext.getSystemService(Context.ALARM_SERVICE))
.thenReturn(mAlarmManager.getAlarmManager());
mUserStore = new MockStoreFile();
mSharedStore = new MockStoreFile();
}
/**
* Setup the test environment.
*/
@Before
public void setUp() throws Exception {
setupMocks();
mWifiConfigStore = new WifiConfigStore(mContext, mLooper.getLooper(), mClock, mSharedStore);
// Enable verbose logging before tests.
mWifiConfigStore.enableVerboseLogging(true);
}
/**
* Called after each test
*/
@After
public void cleanup() {
validateMockitoUsage();
}
/**
* Tests the write API with the force flag set to true.
* Expected behavior: This should trigger an immediate write to the store files and no alarms
* should be started.
*/
@Test
public void testForceWrite() throws Exception {
mWifiConfigStore.switchUserStoreAndRead(mUserStore);
mWifiConfigStore.write(true, getEmptyStoreData());
assertFalse(mAlarmManager.isPending(WifiConfigStore.BUFFERED_WRITE_ALARM_TAG));
assertTrue(mSharedStore.isStoreWritten());
assertTrue(mUserStore.isStoreWritten());
}
/**
* Tests the write API with the force flag set to false.
* Expected behavior: This should set an alarm to write to the store files.
*/
@Test
public void testBufferedWrite() throws Exception {
mWifiConfigStore.switchUserStoreAndRead(mUserStore);
mWifiConfigStore.write(false, getEmptyStoreData());
assertTrue(mAlarmManager.isPending(WifiConfigStore.BUFFERED_WRITE_ALARM_TAG));
assertFalse(mSharedStore.isStoreWritten());
assertFalse(mUserStore.isStoreWritten());
// Now send the alarm and ensure that the writes happen.
mAlarmManager.dispatch(WifiConfigStore.BUFFERED_WRITE_ALARM_TAG);
mLooper.dispatchAll();
assertTrue(mSharedStore.isStoreWritten());
assertTrue(mUserStore.isStoreWritten());
}
/**
* Tests the force write after a buffered write.
* Expected behaviour: The force write should override the previous buffered write and stop the
* buffer write alarms.
*/
@Test
public void testForceWriteAfterBufferedWrite() throws Exception {
WifiConfigStoreData bufferedStoreData = createSingleOpenNetworkStoreData();
mWifiConfigStore.switchUserStoreAndRead(mUserStore);
mWifiConfigStore.write(false, bufferedStoreData);
assertTrue(mAlarmManager.isPending(WifiConfigStore.BUFFERED_WRITE_ALARM_TAG));
assertFalse(mSharedStore.isStoreWritten());
assertFalse(mUserStore.isStoreWritten());
// Now send a force write and ensure that the writes have been performed and alarms have
// been stopped.
WifiConfigStoreData forcedStoreData = createSinglePskNetworkStoreData();
mWifiConfigStore.write(true, forcedStoreData);
assertFalse(mAlarmManager.isPending(WifiConfigStore.BUFFERED_WRITE_ALARM_TAG));
assertTrue(mSharedStore.isStoreWritten());
assertTrue(mUserStore.isStoreWritten());
// Now deserialize the data and ensure that the configuration retrieved matches the force
// write data.
WifiConfigStoreData retrievedStoreData =
WifiConfigStoreData.parseRawData(
mSharedStore.getStoreBytes(), mUserStore.getStoreBytes());
assertConfigStoreDataEqual(forcedStoreData, retrievedStoreData);
}
/**
* Tests the read API behaviour after a write to the store files.
* Expected behaviour: The read should return the same data that was last written.
*/
@Test
public void testReadAfterWrite() throws Exception {
WifiConfigStoreData writeData = createSingleOpenNetworkStoreData();
mWifiConfigStore.switchUserStoreAndRead(mUserStore);
mWifiConfigStore.write(true, writeData);
WifiConfigStoreData readData = mWifiConfigStore.read();
assertConfigStoreDataEqual(writeData, readData);
}
/**
* Tests the read API behaviour when there is no store files on the device.
* Expected behaviour: The read should return an empty store data instance when the file not
* found exception is raised.
*/
@Test
public void testReadWithNoStoreFile() throws Exception {
// Reading the mock store without a write should simulate the file not found case because
// |readRawData| would return null.
assertFalse(mWifiConfigStore.areStoresPresent());
WifiConfigStoreData readData = mWifiConfigStore.read();
assertConfigStoreDataEqual(getEmptyStoreData(), readData);
}
/**
* Tests the read API behaviour after a write to the shared store file when the user
* store file is null.
* Expected behaviour: The read should return the same data that was last written.
*/
@Test
public void testReadAfterWriteWithNoUserStore() throws Exception {
WifiConfigStoreData writeData = createSingleOpenNetworkStoreData();
mWifiConfigStore.write(true, writeData);
WifiConfigStoreData readData = mWifiConfigStore.read();
assertConfigStoreDataEqual(writeData, readData);
}
/**
* Returns an empty store data object.
*/
private WifiConfigStoreData getEmptyStoreData() {
return new WifiConfigStoreData(
new ArrayList<WifiConfiguration>(), new ArrayList<WifiConfiguration>(),
new HashSet<String>());
}
/**
* Returns an store data object with a single open network.
*/
private WifiConfigStoreData createSingleOpenNetworkStoreData() {
List<WifiConfiguration> configurations = new ArrayList<>();
configurations.add(WifiConfigurationTestUtil.createOpenNetwork());
return new WifiConfigStoreData(
configurations, new ArrayList<WifiConfiguration>(), new HashSet<String>());
}
/**
* Returns an store data object with a single psk network.
*/
private WifiConfigStoreData createSinglePskNetworkStoreData() {
List<WifiConfiguration> configurations = new ArrayList<>();
configurations.add(WifiConfigurationTestUtil.createPskNetwork());
return new WifiConfigStoreData(
configurations, new ArrayList<WifiConfiguration>(), new HashSet<String>());
}
/**
* Mock Store File to redirect all file writes from WifiConfigStore to local buffers.
* This can be used to examine the data output by WifiConfigStore.
*/
private class MockStoreFile extends StoreFile {
private byte[] mStoreBytes;
private boolean mStoreWritten;
public MockStoreFile() {
super(new File("MockStoreFile"));
}
@Override
public byte[] readRawData() {
return mStoreBytes;
}
@Override
public void storeRawDataToWrite(byte[] data) {
mStoreBytes = data;
mStoreWritten = false;
}
@Override
public boolean exists() {
return (mStoreBytes != null);
}
public void writeBufferedRawData() {
mStoreWritten = true;
}
public byte[] getStoreBytes() {
return mStoreBytes;
}
public boolean isStoreWritten() {
return mStoreWritten;
}
}
}