/*
 * Copyright (C) 2009 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.accounts;

import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

import android.accounts.Account;
import android.accounts.AccountManagerInternal;
import android.accounts.AuthenticatorDescription;
import android.app.AppOpsManager;
import android.app.Notification;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.content.pm.RegisteredServicesCache.ServiceInfo;
import android.content.pm.RegisteredServicesCacheListener;
import android.content.pm.UserInfo;
import android.database.Cursor;
import android.database.DatabaseErrorHandler;
import android.database.sqlite.SQLiteDatabase;
import android.os.Bundle;
import android.os.Handler;
import android.os.UserHandle;
import android.os.UserManager;
import android.test.AndroidTestCase;
import android.test.mock.MockContext;
import android.test.mock.MockPackageManager;
import android.util.Log;

import com.android.server.LocalServices;

import java.io.File;
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Comparator;

public class AccountManagerServiceTest extends AndroidTestCase {
    private static final String TAG = AccountManagerServiceTest.class.getSimpleName();

    static final String PREN_DB = "pren.db";
    static final String DE_DB = "de.db";
    static final String CE_DB = "ce.db";
    private AccountManagerService mAms;

    @Override
    protected void setUp() throws Exception {
        Context realTestContext = getContext();
        Context mockContext = new MyMockContext(realTestContext);
        setContext(mockContext);
        mAms = createAccountManagerService(mockContext, realTestContext);
    }

    @Override
    protected void tearDown() throws Exception {
        SQLiteDatabase.deleteDatabase(new File(mAms.getCeDatabaseName(UserHandle.USER_SYSTEM)));
        SQLiteDatabase.deleteDatabase(new File(mAms.getDeDatabaseName(UserHandle.USER_SYSTEM)));
        SQLiteDatabase.deleteDatabase(new File(mAms.getPreNDatabaseName(UserHandle.USER_SYSTEM)));
        LocalServices.removeServiceForTest(AccountManagerInternal.class);
        super.tearDown();
    }

    public class AccountSorter implements Comparator<Account> {
        public int compare(Account object1, Account object2) {
            if (object1 == object2) return 0;
            if (object1 == null) return 1;
            if (object2 == null) return -1;
            int result = object1.type.compareTo(object2.type);
            if (result != 0) return result;
            return object1.name.compareTo(object2.name);
        }
    }

    public void testCheckAddAccount() throws Exception {
        unlockSystemUser();
        Account a11 = new Account("account1", "type1");
        Account a21 = new Account("account2", "type1");
        Account a31 = new Account("account3", "type1");
        Account a12 = new Account("account1", "type2");
        Account a22 = new Account("account2", "type2");
        Account a32 = new Account("account3", "type2");
        mAms.addAccountExplicitly(a11, "p11", null);
        mAms.addAccountExplicitly(a12, "p12", null);
        mAms.addAccountExplicitly(a21, "p21", null);
        mAms.addAccountExplicitly(a22, "p22", null);
        mAms.addAccountExplicitly(a31, "p31", null);
        mAms.addAccountExplicitly(a32, "p32", null);

        Account[] accounts = mAms.getAccounts(null, mContext.getOpPackageName());
        Arrays.sort(accounts, new AccountSorter());
        assertEquals(6, accounts.length);
        assertEquals(a11, accounts[0]);
        assertEquals(a21, accounts[1]);
        assertEquals(a31, accounts[2]);
        assertEquals(a12, accounts[3]);
        assertEquals(a22, accounts[4]);
        assertEquals(a32, accounts[5]);

        accounts = mAms.getAccounts("type1", mContext.getOpPackageName());
        Arrays.sort(accounts, new AccountSorter());
        assertEquals(3, accounts.length);
        assertEquals(a11, accounts[0]);
        assertEquals(a21, accounts[1]);
        assertEquals(a31, accounts[2]);

        mAms.removeAccountInternal(a21);

        accounts = mAms.getAccounts("type1", mContext.getOpPackageName());
        Arrays.sort(accounts, new AccountSorter());
        assertEquals(2, accounts.length);
        assertEquals(a11, accounts[0]);
        assertEquals(a31, accounts[1]);
    }

    public void testPasswords() throws Exception {
        unlockSystemUser();
        Account a11 = new Account("account1", "type1");
        Account a12 = new Account("account1", "type2");
        mAms.addAccountExplicitly(a11, "p11", null);
        mAms.addAccountExplicitly(a12, "p12", null);

        assertEquals("p11", mAms.getPassword(a11));
        assertEquals("p12", mAms.getPassword(a12));

        mAms.setPassword(a11, "p11b");

        assertEquals("p11b", mAms.getPassword(a11));
        assertEquals("p12", mAms.getPassword(a12));
    }

    public void testUserdata() throws Exception {
        unlockSystemUser();
        Account a11 = new Account("account1", "type1");
        Bundle u11 = new Bundle();
        u11.putString("a", "a_a11");
        u11.putString("b", "b_a11");
        u11.putString("c", "c_a11");
        Account a12 = new Account("account1", "type2");
        Bundle u12 = new Bundle();
        u12.putString("a", "a_a12");
        u12.putString("b", "b_a12");
        u12.putString("c", "c_a12");
        mAms.addAccountExplicitly(a11, "p11", u11);
        mAms.addAccountExplicitly(a12, "p12", u12);

        assertEquals("a_a11", mAms.getUserData(a11, "a"));
        assertEquals("b_a11", mAms.getUserData(a11, "b"));
        assertEquals("c_a11", mAms.getUserData(a11, "c"));
        assertEquals("a_a12", mAms.getUserData(a12, "a"));
        assertEquals("b_a12", mAms.getUserData(a12, "b"));
        assertEquals("c_a12", mAms.getUserData(a12, "c"));

        mAms.setUserData(a11, "b", "b_a11b");
        mAms.setUserData(a12, "c", null);

        assertEquals("a_a11", mAms.getUserData(a11, "a"));
        assertEquals("b_a11b", mAms.getUserData(a11, "b"));
        assertEquals("c_a11", mAms.getUserData(a11, "c"));
        assertEquals("a_a12", mAms.getUserData(a12, "a"));
        assertEquals("b_a12", mAms.getUserData(a12, "b"));
        assertNull(mAms.getUserData(a12, "c"));
    }

    public void testAuthtokens() throws Exception {
        unlockSystemUser();
        Account a11 = new Account("account1", "type1");
        Account a12 = new Account("account1", "type2");
        mAms.addAccountExplicitly(a11, "p11", null);
        mAms.addAccountExplicitly(a12, "p12", null);

        mAms.setAuthToken(a11, "att1", "a11_att1");
        mAms.setAuthToken(a11, "att2", "a11_att2");
        mAms.setAuthToken(a11, "att3", "a11_att3");
        mAms.setAuthToken(a12, "att1", "a12_att1");
        mAms.setAuthToken(a12, "att2", "a12_att2");
        mAms.setAuthToken(a12, "att3", "a12_att3");

        assertEquals("a11_att1", mAms.peekAuthToken(a11, "att1"));
        assertEquals("a11_att2", mAms.peekAuthToken(a11, "att2"));
        assertEquals("a11_att3", mAms.peekAuthToken(a11, "att3"));
        assertEquals("a12_att1", mAms.peekAuthToken(a12, "att1"));
        assertEquals("a12_att2", mAms.peekAuthToken(a12, "att2"));
        assertEquals("a12_att3", mAms.peekAuthToken(a12, "att3"));

        mAms.setAuthToken(a11, "att3", "a11_att3b");
        mAms.invalidateAuthToken(a12.type, "a12_att2");

        assertEquals("a11_att1", mAms.peekAuthToken(a11, "att1"));
        assertEquals("a11_att2", mAms.peekAuthToken(a11, "att2"));
        assertEquals("a11_att3b", mAms.peekAuthToken(a11, "att3"));
        assertEquals("a12_att1", mAms.peekAuthToken(a12, "att1"));
        assertNull(mAms.peekAuthToken(a12, "att2"));
        assertEquals("a12_att3", mAms.peekAuthToken(a12, "att3"));

        assertNull(mAms.peekAuthToken(a12, "att2"));
    }

    public void testRemovedAccountSync() throws Exception {
        unlockSystemUser();
        Account a1 = new Account("account1", "type1");
        Account a2 = new Account("account2", "type2");
        mAms.addAccountExplicitly(a1, "p1", null);
        mAms.addAccountExplicitly(a2, "p2", null);

        Context originalContext = ((MyMockContext)getContext()).mTestContext;
        // create a separate instance of AMS. It initially assumes that user0 is locked
        AccountManagerService ams2 = createAccountManagerService(getContext(), originalContext);

        // Verify that account can be removed when user is locked
        ams2.removeAccountInternal(a1);
        Account[] accounts = ams2.getAccounts(UserHandle.USER_SYSTEM, mContext.getOpPackageName());
        assertEquals(1, accounts.length);
        assertEquals("Only a2 should be returned", a2, accounts[0]);

        // Verify that CE db file is unchanged and still has 2 accounts
        String ceDatabaseName = mAms.getCeDatabaseName(UserHandle.USER_SYSTEM);
        int accountsNumber = readNumberOfAccountsFromDbFile(originalContext, ceDatabaseName);
        assertEquals("CE database should still have 2 accounts", 2, accountsNumber);

        // Unlock the user and verify that db has been updated
        ams2.onUserUnlocked(newIntentForUser(UserHandle.USER_SYSTEM));
        accountsNumber = readNumberOfAccountsFromDbFile(originalContext, ceDatabaseName);
        assertEquals("CE database should now have 1 account", 2, accountsNumber);
        accounts = ams2.getAccounts(UserHandle.USER_SYSTEM, mContext.getOpPackageName());
        assertEquals(1, accounts.length);
        assertEquals("Only a2 should be returned", a2, accounts[0]);
    }

    public void testPreNDatabaseMigration() throws Exception {
        String preNDatabaseName = mAms.getPreNDatabaseName(UserHandle.USER_SYSTEM);
        Context originalContext = ((MyMockContext) getContext()).mTestContext;
        PreNTestDatabaseHelper.createV4Database(originalContext, preNDatabaseName);
        // Assert that database was created with 1 account
        int n = readNumberOfAccountsFromDbFile(originalContext, preNDatabaseName);
        assertEquals("pre-N database should have 1 account", 1, n);

        // Start testing
        unlockSystemUser();
        Account[] accounts = mAms.getAccounts(null, mContext.getOpPackageName());
        assertEquals("1 account should be migrated", 1, accounts.length);
        assertEquals(PreNTestDatabaseHelper.ACCOUNT_NAME, accounts[0].name);
        assertEquals(PreNTestDatabaseHelper.ACCOUNT_PASSWORD, mAms.getPassword(accounts[0]));
        assertEquals("Authtoken should be migrated",
                PreNTestDatabaseHelper.TOKEN_STRING,
                mAms.peekAuthToken(accounts[0], PreNTestDatabaseHelper.TOKEN_TYPE));

        assertFalse("pre-N database file should be removed but was found at " + preNDatabaseName,
                new File(preNDatabaseName).exists());

        // Verify that ce/de files are present
        String deDatabaseName = mAms.getDeDatabaseName(UserHandle.USER_SYSTEM);
        String ceDatabaseName = mAms.getCeDatabaseName(UserHandle.USER_SYSTEM);
        assertTrue("DE database file should be created at " + deDatabaseName,
                new File(deDatabaseName).exists());
        assertTrue("CE database file should be created at " + ceDatabaseName,
                new File(ceDatabaseName).exists());
    }

    private int readNumberOfAccountsFromDbFile(Context context, String dbName) {
        SQLiteDatabase ceDb = context.openOrCreateDatabase(dbName, 0, null);
        try (Cursor cursor = ceDb.rawQuery("SELECT count(*) FROM accounts", null)) {
            assertTrue(cursor.moveToNext());
            return cursor.getInt(0);
        }
    }

    private AccountManagerService createAccountManagerService(Context mockContext,
            Context realContext) {
        LocalServices.removeServiceForTest(AccountManagerInternal.class);
        return new MyAccountManagerService(mockContext,
                new MyMockPackageManager(), new MockAccountAuthenticatorCache(), realContext);
    }

    private void unlockSystemUser() {
        mAms.onUserUnlocked(newIntentForUser(UserHandle.USER_SYSTEM));
    }

    private static Intent newIntentForUser(int userId) {
        Intent intent = new Intent();
        intent.putExtra(Intent.EXTRA_USER_HANDLE, userId);
        return intent;
    }

    static public class MockAccountAuthenticatorCache implements IAccountAuthenticatorCache {
        private ArrayList<ServiceInfo<AuthenticatorDescription>> mServices;

        public MockAccountAuthenticatorCache() {
            mServices = new ArrayList<>();
            AuthenticatorDescription d1 = new AuthenticatorDescription("type1", "p1", 0, 0, 0, 0);
            AuthenticatorDescription d2 = new AuthenticatorDescription("type2", "p2", 0, 0, 0, 0);
            mServices.add(new ServiceInfo<>(d1, null, null));
            mServices.add(new ServiceInfo<>(d2, null, null));
        }

        @Override
        public ServiceInfo<AuthenticatorDescription> getServiceInfo(
                AuthenticatorDescription type, int userId) {
            for (ServiceInfo<AuthenticatorDescription> service : mServices) {
                if (service.type.equals(type)) {
                    return service;
                }
            }
            return null;
        }

        @Override
        public Collection<ServiceInfo<AuthenticatorDescription>> getAllServices(int userId) {
            return mServices;
        }

        @Override
        public void dump(
                final FileDescriptor fd, final PrintWriter fout, final String[] args, int userId) {
        }

        @Override
        public void setListener(
                final RegisteredServicesCacheListener<AuthenticatorDescription> listener,
                final Handler handler) {
        }

        @Override
        public void invalidateCache(int userId) {
        }

        @Override
        public void updateServices(int userId) {
        }
    }

    static public class MyMockContext extends MockContext {
        private Context mTestContext;
        private AppOpsManager mAppOpsManager;
        private UserManager mUserManager;
        private PackageManager mPackageManager;

        public MyMockContext(Context testContext) {
            this.mTestContext = testContext;
            this.mAppOpsManager = mock(AppOpsManager.class);
            this.mUserManager = mock(UserManager.class);
            this.mPackageManager = mock(PackageManager.class);
            final UserInfo ui = new UserInfo(UserHandle.USER_SYSTEM, "user0", 0);
            when(mUserManager.getUserInfo(eq(ui.id))).thenReturn(ui);
        }

        @Override
        public int checkCallingOrSelfPermission(final String permission) {
            return PackageManager.PERMISSION_GRANTED;
        }

        @Override
        public PackageManager getPackageManager() {
            return mPackageManager;
        }

        @Override
        public Object getSystemService(String name) {
            if (Context.APP_OPS_SERVICE.equals(name)) {
                return mAppOpsManager;
            } else if( Context.USER_SERVICE.equals(name)) {
                return mUserManager;
            }
            return null;
        }

        @Override
        public String getSystemServiceName(Class<?> serviceClass) {
            if (AppOpsManager.class.equals(serviceClass)) {
                return Context.APP_OPS_SERVICE;
            }
            return null;
        }

        @Override
        public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter) {
            return null;
        }

        @Override
        public Intent registerReceiverAsUser(BroadcastReceiver receiver, UserHandle user,
                IntentFilter filter, String broadcastPermission, Handler scheduler) {
            return null;
        }

        @Override
        public SQLiteDatabase openOrCreateDatabase(String file, int mode,
                SQLiteDatabase.CursorFactory factory, DatabaseErrorHandler errorHandler) {
            Log.i(TAG, "openOrCreateDatabase " + file + " mode " + mode);
            return mTestContext.openOrCreateDatabase(file, mode, factory,errorHandler);
        }

        @Override
        public void sendBroadcastAsUser(Intent intent, UserHandle user) {
            Log.i(TAG, "sendBroadcastAsUser " + intent + " " + user);
        }

        @Override
        public String getOpPackageName() {
            return null;
        }
    }

    static public class MyMockPackageManager extends MockPackageManager {
        @Override
        public int checkSignatures(final int uid1, final int uid2) {
            return PackageManager.SIGNATURE_MATCH;
        }

        @Override
        public void addOnPermissionsChangeListener(
                OnPermissionsChangedListener listener) {
        }
    }

    static public class MyAccountManagerService extends AccountManagerService {
        private Context mRealTestContext;
        public MyAccountManagerService(Context context, PackageManager packageManager,
                IAccountAuthenticatorCache authenticatorCache, Context realTestContext) {
            super(context, packageManager, authenticatorCache);
            this.mRealTestContext = realTestContext;
        }

        @Override
        protected void installNotification(final int notificationId, final Notification n, UserHandle user) {
        }

        @Override
        protected void cancelNotification(final int id, UserHandle user) {
        }

        @Override
        protected String getCeDatabaseName(int userId) {
            return new File(mRealTestContext.getCacheDir(), CE_DB).getPath();
        }

        @Override
        protected String getDeDatabaseName(int userId) {
            return new File(mRealTestContext.getCacheDir(), DE_DB).getPath();
        }

        @Override
        String getPreNDatabaseName(int userId) {
            return new File(mRealTestContext.getCacheDir(), PREN_DB).getPath();
        }
    }
}
