// Copyright 2018 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

use anyhow::{format_err, Error};
use fidl::endpoints::{RequestStream, ServerEnd};
use fidl_fuchsia_stash::{
    FlushError, GetIteratorMarker, GetIteratorRequest, GetIteratorRequestStream, KeyValue,
    ListItem, ListIteratorMarker, ListIteratorRequest, ListIteratorRequestStream, Value,
};
use fuchsia_async as fasync;
use fuchsia_zircon::sys::ZX_CHANNEL_MAX_MSG_BYTES;
use futures::lock::Mutex;
use futures::{TryFutureExt, TryStreamExt};
use measure_tape_for_stash::Measurable as _;
use std::collections::HashMap;
use std::sync::Arc;
use tracing::warn;

use crate::store;

/// Accessors are used by clients to view and interact with the store. In this situation, that
/// means handling transactional logic and using the store_manager to perform store
/// lookups/manipulations.
pub struct Accessor {
    store_manager: Arc<Mutex<store::StoreManager>>,
    client_name: String,
    enable_bytes: bool,
    read_only: bool,
    fields_updated: Arc<Mutex<HashMap<store::Key, Option<Value>>>>,
}

impl Accessor {
    /// Create a new accessor for interacting with the store. The client_name field determines what
    /// namespace in the store will be used.
    pub fn new(
        store_manager: Arc<Mutex<store::StoreManager>>,
        enable_bytes: bool,
        read_only: bool,
        client_name: String,
    ) -> Accessor {
        Accessor {
            store_manager,
            enable_bytes,
            client_name,
            read_only,
            fields_updated: Arc::new(Mutex::new(HashMap::new())),
        }
    }

    /// Retrieves a value from the store. If a value has been modified and commit() hasn't been
    /// called yet, the modified version will be returned.
    pub async fn get_value<'a>(&'a self, key: &'a str) -> Result<Option<Value>, Error> {
        let store_manager = self.store_manager.lock().await;

        if let Some(o_val) = self.fields_updated.lock().await.get(key) {
            // This accessor has an uncommited update for the field, so let's return that.
            match (self.enable_bytes, o_val) {
                (false, Some(Value::Bytesval(_))) => {
                    // Bytes are disabled. Return an error instead.
                    return Err(format_err!(
                        "client attempted to access bytes when the type is disabled",
                    ));
                }
                (_, Some(val)) => {
                    return Ok(Some(store::clone_value(val)?));
                }
                (_, None) => return Ok(None),
            }
        }

        let res = store_manager.get_value(&self.client_name, &key);

        match res {
            None => Ok(None),
            Some(Value::Bytesval(_)) if !self.enable_bytes => {
                Err(format_err!("client attempted to access bytes when the type is disabled"))
            }
            Some(val) => Ok(Some(store::clone_value(val)?)),
        }
    }

    /// Sets a value in the store. commit() must be called for this to take effect.
    pub async fn set_value(&mut self, key: String, val: Value) -> Result<(), Error> {
        if self.read_only {
            return Err(format_err!("client attempted to set a value with a read-only accessor"));
        }
        if !self.enable_bytes {
            if let Value::Bytesval(_) = val {
                return Err(format_err!("client attempted to set bytes when the type is disabled"));
            }
        }

        self.fields_updated.lock().await.insert(key, Some(val));

        Ok(())
    }

    /// Deletes a value from the store. commit() must be called for this to take effect.
    pub async fn delete_value(&mut self, key: String) -> Result<(), Error> {
        if self.read_only {
            return Err(format_err!(
                "client attempted to delete a value with a read-only accessor"
            ));
        }

        self.fields_updated.lock().await.insert(key, None);
        Ok(())
    }

    /// Given a server endpoint, answers calls to get_next on the endpoint to return key/type pairs
    /// where the key contains the given prefix.
    pub async fn list_prefix(&mut self, prefix: String, server_end: ServerEnd<ListIteratorMarker>) {
        let mut list_results =
            self.store_manager.lock().await.list_prefix(&self.client_name, &prefix);

        // Merge the results with the pending updated fields
        let fields_updated = self.fields_updated.lock().await;
        if !fields_updated.is_empty() {
            // Delete any fields that have been marked for removal
            list_results.retain(|li| field_has_been_deleted(fields_updated.get(&li.key)));
            // Update any fields that have been updated/created
            for (key, o_val) in fields_updated.iter() {
                let mut key_was_added = false;
                for li in list_results.iter_mut() {
                    if let Some(v) = o_val {
                        if &li.key == key {
                            key_was_added = true;
                            li.type_ = store::value_to_type(&v);
                        }
                    }
                }
                // This is a new key, append it to the results.
                if !key_was_added {
                    if let Some(v) = o_val {
                        list_results
                            .push(ListItem { key: key.clone(), type_: store::value_to_type(&v) });
                    }
                }
            }
        }

        fasync::Task::spawn(
            async move {
                let server_chan = fasync::Channel::from_channel(server_end.into_channel())?;
                let mut stream = ListIteratorRequestStream::from_channel(server_chan);
                let mut iter = list_results.into_iter();
                while let Some(ListIteratorRequest::GetNext { responder }) =
                    stream.try_next().await?
                {
                    // 16 byte overhead for response header
                    // 16 byte overhead for vector header
                    let mut bytes_used: usize = 32;

                    let mut item_index = 0;
                    for result in iter.clone() {
                        bytes_used += result.measure().num_bytes;
                        if bytes_used > ZX_CHANNEL_MAX_MSG_BYTES as usize {
                            break;
                        }
                        item_index += 1;
                    }
                    let mut chunk: Vec<_> = iter.by_ref().take(item_index).collect();
                    responder.send(&mut chunk.iter_mut())?;
                }
                Ok(())
            }
            .unwrap_or_else(|err: anyhow::Error| {
                // TODO(fxbug.dev/62386) - determine which errors are stash failures and log them
                // with error severity
                warn!(?err, "error running list prefix interface")
            }),
        )
        .detach();
    }

    /// Given a server endpoint, answers calls to get_next on the endpoint to return key/value
    /// pairs where the key contains the given prefix.
    pub async fn get_prefix(
        &mut self,
        prefix: String,
        server_end: ServerEnd<GetIteratorMarker>,
    ) -> Result<(), Error> {
        let mut get_results =
            self.store_manager.lock().await.get_prefix(&self.client_name, &prefix)?;

        // Merge the results with the pending updated fields
        let fields_updated = self.fields_updated.lock().await;
        if !fields_updated.is_empty() {
            // Delete any fields that have been marked for removal
            get_results.retain(|kv| field_has_been_deleted(fields_updated.get(&kv.key)));
            // Update any fields that have been updated/created
            for (key, o_val) in fields_updated.iter() {
                let mut key_was_added = false;
                for kv in get_results.iter_mut() {
                    if let Some(v) = o_val {
                        if &kv.key == key {
                            key_was_added = true;
                            kv.val = store::clone_value(v)?;
                        }
                    }
                }
                // This is a new key, append it to the results.
                if !key_was_added {
                    if let Some(v) = o_val {
                        get_results
                            .push(KeyValue { key: key.clone(), val: store::clone_value(v)? });
                    }
                }
            }
        }

        let enable_bytes = self.enable_bytes;

        fasync::Task::spawn(
            async move {
                let server_chan = fasync::Channel::from_channel(server_end.into_channel())?;
                let mut stream = GetIteratorRequestStream::from_channel(server_chan);

                if !enable_bytes {
                    for item in get_results.iter() {
                        if let Value::Bytesval(_) = item.val {
                            Err(format_err!(
                                "client attempted to access bytes when the type is disabled",
                            ))?;
                        }
                    }
                }

                let mut iter = get_results.into_iter().peekable();
                while let Some(GetIteratorRequest::GetNext { responder }) =
                    stream.try_next().await?
                {
                    let mut chunk = vec![];

                    // 16 byte overhead for vectors
                    // 16 byte overhead per string
                    let mut bytes_used: usize = 32;

                    loop {
                        match iter.peek() {
                            None => break,
                            Some(next_item) => {
                                bytes_used += next_item.measure().num_bytes;
                                if bytes_used > ZX_CHANNEL_MAX_MSG_BYTES as usize {
                                    break;
                                }
                            }
                        }
                        chunk.push(iter.next().unwrap());
                    }

                    responder.send(&mut chunk.iter_mut())?;
                }
                Ok(())
            }
            .unwrap_or_else(|err: anyhow::Error| {
                // TODO(fxbug.dev/62386) - determine which errors are stash failures and log them
                // with error severity
                warn!(?err, "error running get prefix interface");
            }),
        )
        .detach();
        Ok(())
    }

    /// Deletes all keys under a given prefix. commit() must be called for this to take effect.
    pub async fn delete_prefix(&mut self, prefix: String) -> Result<(), Error> {
        if self.read_only {
            return Err(format_err!(
                "client attempted to delete a prefix with a read-only accessor"
            ));
        }

        let sm = self.store_manager.lock().await;
        let mut fields_updated = self.fields_updated.lock().await;

        let list_results = sm.list_prefix(&self.client_name, &prefix);

        for (key, o_val) in fields_updated.iter_mut() {
            if key.starts_with(&prefix) {
                *o_val = None;
            }
        }
        for li in list_results {
            fields_updated.insert(li.key, None);
        }
        Ok(())
    }

    /// Causes all state modifications to take effect and be written to disk atomically.
    pub async fn commit(&mut self) -> Result<(), Error> {
        if self.read_only {
            return Err(format_err!("client attempted to commit with a read-only accessor"));
        }

        let mut store_manager = self.store_manager.lock().await;
        let mut fields_updated = self.fields_updated.lock().await;
        let mut old_values: HashMap<String, Option<Value>> = HashMap::new();

        // Iterate over each key updated. For each key, record the current value and then set or
        // delete it as appropriate. If an error is encountered, break out of the loop and use the
        // values we just recorded to undo the changes we made.

        let commit_result = (|| {
            for (key, o_val) in fields_updated.iter() {
                {
                    let o_old_value = store_manager.get_value(&self.client_name, key);
                    let old_value = match o_old_value {
                        Some(val_ref) => Some(store::clone_value(val_ref)?),
                        None => None,
                    };
                    old_values.insert(key.clone(), old_value);
                }

                match o_val {
                    Some(val) => store_manager.set_value(
                        &self.client_name,
                        key.clone(),
                        store::clone_value(val)?,
                    )?,
                    None => store_manager.delete_value(&self.client_name, key)?,
                }
            }
            Ok(())
        })();
        fields_updated.clear();
        if commit_result.is_ok() {
            return commit_result;
        }
        // There was a problem. Revert the changes.
        for (key, o_val) in old_values.iter() {
            match o_val {
                // TODO: on an error here, should we bail out immediately (current response),
                // or continue and attempt to revert as many changes as we can? Does a
                // partially-committed accessor mean that the store is now corrupted?
                Some(val) => {
                    store_manager.set_value(
                        &self.client_name,
                        key.clone(),
                        store::clone_value(val)?,
                    )?;
                }
                None => {
                    store_manager.delete_value(&self.client_name, key)?;
                }
            }
        }
        return commit_result;
    }

    pub async fn flush(&mut self) -> Result<(), FlushError> {
        if self.read_only {
            Err(FlushError::ReadOnly)
        } else {
            self.commit().await.or(Err(FlushError::CommitFailed))
        }
    }
}

// A helper function for use in list_prefix and get_prefix
fn field_has_been_deleted<T>(f: Option<&Option<T>>) -> bool {
    match f {
        // The key has not been updated, keep it
        None => true,
        // The key has been marked for removal, drop it
        Some(None) => false,
        // The key has been updated to a new value, keep it
        Some(Some(_)) => true,
    }
}

#[cfg(test)]
mod tests {
    use crate::accessor::*;
    use crate::store;
    use fidl::client::QueryResponseFut;
    use fidl::endpoints::create_proxy;
    use fidl_fuchsia_stash::{ListItem, Value};
    use futures::lock::Mutex;
    use std::sync::Arc;
    use tempfile::TempDir;

    fn get_tmp_store_manager(tmp_dir: &TempDir) -> store::StoreManager {
        store::StoreManager::new(tmp_dir.path().join("stash.store")).unwrap()
    }

    async fn drain_stash_iterator<T, F>(mut f: F) -> Vec<T>
    where
        F: FnMut() -> QueryResponseFut<Vec<T>>,
        T: Unpin,
    {
        let mut res = Vec::new();
        loop {
            let mut subset = f().await.unwrap();
            if subset.len() == 0 {
                break;
            }
            res.append(&mut subset);
        }
        res
    }

    #[fuchsia::test]
    async fn test_get_value() {
        let test_client_name = "test_client".to_string();
        let test_key = "test_key".to_string();

        let tmp_dir = TempDir::new().unwrap();
        let sm = Arc::new(Mutex::new(get_tmp_store_manager(&tmp_dir)));
        let acc = Accessor::new(sm.clone(), true, false, test_client_name.clone());

        sm.lock()
            .await
            .set_value(&test_client_name, test_key.clone(), Value::Boolval(true))
            .unwrap();

        let fetched_val = acc.get_value(&test_key).await.unwrap();
        assert_eq!(Some(Value::Boolval(true)), fetched_val);
        assert_eq!(0, acc.fields_updated.lock().await.len());
    }

    #[fuchsia::test]
    async fn test_set_value() {
        let test_client_name = "test_client".to_string();
        let test_key = "test_key".to_string();

        let tmp_dir = TempDir::new().unwrap();
        let sm = Arc::new(Mutex::new(get_tmp_store_manager(&tmp_dir)));
        let mut acc = Accessor::new(sm.clone(), true, false, test_client_name.clone());

        let test_val = Value::Boolval(true);
        let expected_val = Value::Boolval(true);

        acc.set_value(test_key.clone(), test_val).await.unwrap();
        assert_eq!(None, sm.lock().await.get_value(&test_client_name, &test_key));
        assert_eq!(1, acc.fields_updated.lock().await.len());
        assert_eq!(&Some(expected_val), acc.fields_updated.lock().await.get(&test_key).unwrap());

        assert_eq!(None, sm.lock().await.get_value(&test_client_name, &test_key));

        acc.commit().await.unwrap();
        assert_eq!(
            &Value::Boolval(true),
            sm.lock().await.get_value(&test_client_name, &test_key).unwrap()
        );
        assert_eq!(0, acc.fields_updated.lock().await.len());
    }

    #[fuchsia::test]
    async fn test_delete_value() {
        let test_client_name = "test_client".to_string();

        let tmp_dir = TempDir::new().unwrap();
        let sm = Arc::new(Mutex::new(get_tmp_store_manager(&tmp_dir)));
        let mut acc = Accessor::new(sm.clone(), true, false, test_client_name.clone());

        sm.lock()
            .await
            .set_value(&test_client_name, "a".to_string(), Value::Boolval(true))
            .unwrap();

        assert_eq!(0, acc.fields_updated.lock().await.len());
        acc.delete_value("b".to_string()).await.unwrap();
        assert_eq!(1, acc.fields_updated.lock().await.len());

        acc.delete_value("a".to_string()).await.unwrap();
        assert_eq!(2, acc.fields_updated.lock().await.len());
        assert_eq!(&None, acc.fields_updated.lock().await.get("a").unwrap());

        acc.delete_value("a".to_string()).await.unwrap();
        assert_eq!(2, acc.fields_updated.lock().await.len());
        assert_eq!(&None, acc.fields_updated.lock().await.get("a").unwrap());

        assert_eq!(
            Some(&Value::Boolval(true)),
            sm.lock().await.get_value(&test_client_name, &"a".to_string())
        );

        acc.commit().await.unwrap();
        assert_eq!(None, sm.lock().await.get_value(&test_client_name, &"a".to_string()));
        assert_eq!(0, acc.fields_updated.lock().await.len());
    }

    #[fuchsia::test]
    async fn test_list_prefix() {
        let test_client_name = "test_client".to_string();

        let tmp_dir = TempDir::new().unwrap();
        let sm = Arc::new(Mutex::new(get_tmp_store_manager(&tmp_dir)));

        for key in vec!["a", "a/a", "a/b", "a/a/b", "b", "b/c", "bbbbb"] {
            sm.lock()
                .await
                .set_value(&test_client_name, key.to_string(), Value::Boolval(true))
                .unwrap();
        }

        let run_test = |sm: Arc<Mutex<store::StoreManager>>,
                        prefix: String,
                        mut expected: Vec<String>| {
            async move {
                let mut acc = Accessor::new(sm, true, false, "test_client".to_string());
                let (list_iterator, server_end) = create_proxy().unwrap();
                acc.list_prefix(prefix.to_string(), server_end).await;

                let actual = drain_stash_iterator(|| list_iterator.get_next()).await;
                let mut actual: Vec<String> = actual.iter().map(|li| li.key.clone()).collect();

                expected.sort_unstable();
                actual.sort_unstable();
                assert_eq!(expected, actual);
            }
        };

        run_test(
            sm.clone(),
            "".to_string(),
            vec!["a", "a/a", "a/b", "a/a/b", "b", "b/c", "bbbbb"]
                .iter()
                .map(|s| s.to_string())
                .collect(),
        )
        .await;
        run_test(
            sm.clone(),
            "a".to_string(),
            vec!["a", "a/a", "a/b", "a/a/b"].iter().map(|s| s.to_string()).collect(),
        )
        .await;
        run_test(
            sm.clone(),
            "a/a".to_string(),
            vec!["a/a", "a/a/b"].iter().map(|s| s.to_string()).collect(),
        )
        .await;
        run_test(
            sm.clone(),
            "b".to_string(),
            vec!["b", "b/c", "bbbbb"].iter().map(|s| s.to_string()).collect(),
        )
        .await;
        run_test(
            sm.clone(),
            "bb".to_string(),
            vec!["bbbbb"].iter().map(|s| s.to_string()).collect(),
        )
        .await;
        run_test(sm.clone(), "c".to_string(), vec![]).await;
    }

    #[fuchsia::test]
    async fn test_list_prefix_paging() {
        let tmp_dir = TempDir::new().unwrap();
        let sm = Arc::new(Mutex::new(get_tmp_store_manager(&tmp_dir)));

        for key in vec!["a", "a/a", "a/b", "a/a/b", "b", "b/c", "bbbbb"] {
            sm.lock()
                .await
                .set_value("test_client", key.to_string(), Value::Boolval(true))
                .unwrap();
        }

        let run_test = |sm: Arc<Mutex<store::StoreManager>>,
                        prefix: String,
                        mut expected: Vec<String>| {
            async move {
                let mut acc = Accessor::new(sm, true, false, "test_client".to_string());
                let (list_iterator, server_end) = create_proxy().unwrap();
                acc.list_prefix(prefix.to_string(), server_end).await;

                let actual = drain_stash_iterator(|| list_iterator.get_next()).await;
                let mut actual: Vec<String> = actual.iter().map(|li| li.key.clone()).collect();

                expected.sort_unstable();
                actual.sort_unstable();
                assert_eq!(expected, actual);
            }
        };

        run_test(
            sm.clone(),
            "".to_string(),
            vec!["a", "a/a", "a/b", "a/a/b", "b", "b/c", "bbbbb"]
                .iter()
                .map(|s| s.to_string())
                .collect(),
        )
        .await;
        run_test(
            sm.clone(),
            "a".to_string(),
            vec!["a", "a/a", "a/b", "a/a/b"].iter().map(|s| s.to_string()).collect(),
        )
        .await;
        run_test(
            sm.clone(),
            "a/a".to_string(),
            vec!["a/a", "a/a/b"].iter().map(|s| s.to_string()).collect(),
        )
        .await;
        run_test(
            sm.clone(),
            "b".to_string(),
            vec!["b", "b/c", "bbbbb"].iter().map(|s| s.to_string()).collect(),
        )
        .await;
        run_test(
            sm.clone(),
            "bb".to_string(),
            vec!["bbbbb"].iter().map(|s| s.to_string()).collect(),
        )
        .await;
        run_test(sm.clone(), "c".to_string(), vec![]).await;
    }

    #[fuchsia::test]
    async fn test_get_prefix() {
        let tmp_dir = TempDir::new().unwrap();
        let sm = Arc::new(Mutex::new(get_tmp_store_manager(&tmp_dir)));

        for (key, val) in vec![
            ("a", true),
            ("a/a", true),
            ("a/b", false),
            ("a/a/b", false),
            ("b", false),
            ("b/c", true),
            ("bbbbb", true),
        ] {
            sm.lock().await.set_value("test_client", key.to_string(), Value::Boolval(val)).unwrap();
        }

        let run_test = |sm: Arc<Mutex<store::StoreManager>>,
                        prefix: String,
                        mut expected: Vec<(String, bool)>| {
            async move {
                let mut acc = Accessor::new(sm, true, false, "test_client".to_string());
                let (get_iterator, server_end) = create_proxy().unwrap();
                acc.get_prefix(prefix.to_string(), server_end).await.unwrap();

                let mut actual = Vec::new();
                loop {
                    let subset = get_iterator.get_next().await.unwrap();
                    if subset.len() == 0 {
                        break;
                    }
                    for kv in subset.iter() {
                        let b = match kv.val {
                            Value::Boolval(b) => b,
                            _ => panic!("internal test error"),
                        };
                        actual.push((kv.key.clone(), b));
                    }
                }
                expected.sort_unstable();
                actual.sort_unstable();
                assert_eq!(expected, actual);
            }
        };

        run_test(
            sm.clone(),
            "".to_string(),
            vec![
                ("a".to_string(), true),
                ("a/a".to_string(), true),
                ("a/b".to_string(), false),
                ("a/a/b".to_string(), false),
                ("b".to_string(), false),
                ("b/c".to_string(), true),
                ("bbbbb".to_string(), true),
            ],
        )
        .await;
        run_test(
            sm.clone(),
            "a".to_string(),
            vec![
                ("a".to_string(), true),
                ("a/a".to_string(), true),
                ("a/b".to_string(), false),
                ("a/a/b".to_string(), false),
            ],
        )
        .await;
        run_test(
            sm.clone(),
            "a/a".to_string(),
            vec![("a/a".to_string(), true), ("a/a/b".to_string(), false)],
        )
        .await;
        run_test(
            sm.clone(),
            "b".to_string(),
            vec![("b".to_string(), false), ("b/c".to_string(), true), ("bbbbb".to_string(), true)],
        )
        .await;
        run_test(sm.clone(), "bb".to_string(), vec![("bbbbb".to_string(), true)]).await;
        run_test(sm.clone(), "c".to_string(), vec![]).await;
    }

    #[fuchsia::test]
    async fn test_delete_prefix() {
        let test_client_name = "test_client".to_string();

        let tmp_dir = TempDir::new().unwrap();
        let sm = Arc::new(Mutex::new(get_tmp_store_manager(&tmp_dir)));
        let mut acc = Accessor::new(sm.clone(), true, false, test_client_name.clone());

        for key in vec!["a", "a/a", "a/b", "a/a/b", "b", "b/c", "bbbbb"] {
            sm.lock()
                .await
                .set_value(&test_client_name, key.to_string(), Value::Boolval(true))
                .unwrap();
        }

        acc.delete_prefix("a".to_string()).await.unwrap();
        assert_eq!(&None, acc.fields_updated.lock().await.get("a").unwrap());
        assert_eq!(&None, acc.fields_updated.lock().await.get("a/a").unwrap());
        assert_eq!(&None, acc.fields_updated.lock().await.get("a/b").unwrap());
        assert_eq!(&None, acc.fields_updated.lock().await.get("a/a/b").unwrap());
        assert_eq!(4, acc.fields_updated.lock().await.len());
        acc.commit().await.unwrap();

        let (list_iterator, server_end) = create_proxy().unwrap();
        acc.list_prefix("".to_string(), server_end).await;

        let mut actual = Vec::new();
        loop {
            let subset = list_iterator.get_next().await.unwrap();
            if subset.len() == 0 {
                break;
            }
            for ListItem { key, type_: _ } in subset.iter() {
                actual.push(key.clone());
            }
        }
        actual.sort_unstable();
        assert_eq!(vec!["b", "b/c", "bbbbb"], actual);
    }

    #[fuchsia::test]
    async fn test_commit_different_accessors() {
        let test_client_name = "test_client".to_string();

        let tmp_dir = TempDir::new().unwrap();
        let sm = Arc::new(Mutex::new(get_tmp_store_manager(&tmp_dir)));
        let mut acc1 = Accessor::new(sm.clone(), true, false, test_client_name.clone());
        let mut acc2 = Accessor::new(sm.clone(), true, false, test_client_name.clone());

        {
            let mut sm = sm.lock().await;
            sm.set_value(&test_client_name, "a".to_string(), Value::Boolval(true)).unwrap();
            sm.set_value(&test_client_name, "b".to_string(), Value::Boolval(false)).unwrap();
        }

        acc1.get_value("a").await.unwrap();
        acc1.set_value("b".to_string(), Value::Boolval(true)).await.unwrap();

        acc1.commit().await.unwrap();

        assert_eq!(
            &Value::Boolval(true),
            sm.lock().await.get_value(&test_client_name, &"b".to_string()).unwrap()
        );

        acc2.get_value("a").await.unwrap();
        acc2.delete_value("b".to_string()).await.unwrap();

        acc2.commit().await.unwrap();

        assert_eq!(None, sm.lock().await.get_value(&test_client_name, &"b".to_string()));

        // Confirm that the fields touched and fields updated maps have been cleared
        assert_eq!(0, acc1.fields_updated.lock().await.len());
        assert_eq!(0, acc2.fields_updated.lock().await.len());
    }

    #[fuchsia::test]
    async fn test_commit_reuse_accessor() {
        let test_client_name = "test_client".to_string();

        let tmp_dir = TempDir::new().unwrap();
        let sm = Arc::new(Mutex::new(get_tmp_store_manager(&tmp_dir)));
        let mut acc1 = Accessor::new(sm.clone(), true, false, test_client_name.clone());

        {
            let mut sm = sm.lock().await;
            sm.set_value(&test_client_name, "a".to_string(), Value::Boolval(true)).unwrap();
            sm.set_value(&test_client_name, "b".to_string(), Value::Boolval(false)).unwrap();
        }

        acc1.get_value("a").await.unwrap();
        acc1.set_value("b".to_string(), Value::Boolval(true)).await.unwrap();

        acc1.commit().await.unwrap();
        assert_eq!(0, acc1.fields_updated.lock().await.len());

        assert_eq!(
            &Value::Boolval(true),
            sm.lock().await.get_value(&test_client_name, &"b".to_string()).unwrap()
        );

        acc1.get_value("a").await.unwrap();
        acc1.delete_value("b".to_string()).await.unwrap();

        acc1.commit().await.unwrap();
        assert_eq!(0, acc1.fields_updated.lock().await.len());

        assert_eq!(None, sm.lock().await.get_value(&test_client_name, &"b".to_string()));
    }

    #[fuchsia::test]
    async fn test_flush() {
        let test_client_name = "test_client".to_string();
        let tmp_dir = TempDir::new().unwrap();

        {
            let sm = Arc::new(Mutex::new(get_tmp_store_manager(&tmp_dir)));
            let mut acc = Accessor::new(sm.clone(), true, false, test_client_name.clone());

            {
                let mut sm = sm.lock().await;
                sm.set_value(&test_client_name, "a".to_string(), Value::Boolval(false)).unwrap();
            }

            acc.set_value("a".to_string(), Value::Boolval(true)).await.unwrap();

            assert_eq!(acc.flush().await, Ok(()));
        }

        // Create a new store manager, the old one is dropped.
        let sm = Arc::new(Mutex::new(get_tmp_store_manager(&tmp_dir)));

        assert_eq!(
            &Value::Boolval(true),
            sm.lock().await.get_value(&test_client_name, &"a".to_string()).unwrap()
        );
    }

    #[fuchsia::test]
    async fn test_flush_readonly_fails() {
        let test_client_name = "test_client".to_string();
        let tmp_dir = TempDir::new().unwrap();

        let sm = Arc::new(Mutex::new(get_tmp_store_manager(&tmp_dir)));
        let mut acc =
            Accessor::new(sm.clone(), true, true /* read_only */, test_client_name.clone());

        assert_eq!(acc.flush().await, Err(fidl_fuchsia_stash::FlushError::ReadOnly));
    }

    #[fuchsia::test]
    async fn test_flush_commit_fails() {
        let test_client_name = "test_client".to_string();
        let tmp_dir = TempDir::new().unwrap();

        let sm = Arc::new(Mutex::new(get_tmp_store_manager(&tmp_dir)));
        let mut acc =
            Accessor::new(sm.clone(), true, false /* read_only */, test_client_name.clone());
        acc.delete_value("a".to_string()).await.unwrap();

        tmp_dir.close().unwrap();
        assert_eq!(acc.flush().await, Err(fidl_fuchsia_stash::FlushError::CommitFailed));
    }

    #[fuchsia::test]
    async fn test_delete_prefix_considers_current_commit() {
        let test_client_name = "test_client".to_string();

        let tmp_dir = TempDir::new().unwrap();
        let sm = Arc::new(Mutex::new(get_tmp_store_manager(&tmp_dir)));
        let mut acc = Accessor::new(sm.clone(), true, false, test_client_name.clone());

        for key in vec!["a", "aa", "aaa"] {
            acc.set_value(key.to_owned(), Value::Boolval(true)).await.unwrap();
        }
        acc.commit().await.unwrap();
        for key in vec!["b", "bb", "bbb"] {
            acc.set_value(key.to_owned(), Value::Boolval(true)).await.unwrap();
        }

        acc.delete_prefix("".to_string()).await.unwrap();

        let mut keys: Vec<String> =
            acc.fields_updated.lock().await.keys().map(|s| s.clone()).collect();
        keys.sort_unstable();
        assert_eq!(vec!["a", "aa", "aaa", "b", "bb", "bbb"], keys);
        for key in vec!["a", "aa", "aaa", "b", "bb", "bbb"] {
            assert_eq!(Some(&None), acc.fields_updated.lock().await.get(key));
        }
    }

    #[fuchsia::test]
    async fn test_list_prefix_considers_current_commit() {
        let test_client_name = "test_client".to_string();

        let tmp_dir = TempDir::new().unwrap();
        let sm = Arc::new(Mutex::new(get_tmp_store_manager(&tmp_dir)));
        let mut acc = Accessor::new(sm.clone(), true, false, test_client_name.clone());

        for key in vec!["a", "aa", "aaa"] {
            acc.set_value(key.to_owned(), Value::Boolval(true)).await.unwrap();
        }
        acc.commit().await.unwrap();
        for key in vec!["b", "bb", "bbb"] {
            acc.set_value(key.to_owned(), Value::Boolval(true)).await.unwrap();
        }

        let (list_iterator, server_end) = create_proxy().unwrap();
        acc.list_prefix("".to_string(), server_end).await;

        let res = drain_stash_iterator(|| list_iterator.get_next()).await;
        let mut res: Vec<String> = res.iter().map(|li| li.key.clone()).collect();

        res.sort_unstable();
        assert_eq!(vec!["a", "aa", "aaa", "b", "bb", "bbb"], res);
    }

    #[fuchsia::test]
    async fn test_get_prefix_considers_current_commit() {
        let test_client_name = "test_client".to_string();

        let tmp_dir = TempDir::new().unwrap();
        let sm = Arc::new(Mutex::new(get_tmp_store_manager(&tmp_dir)));
        let mut acc = Accessor::new(sm.clone(), true, false, test_client_name.clone());

        for key in vec!["a", "aa", "aaa"] {
            acc.set_value(key.to_owned(), Value::Boolval(true)).await.unwrap();
        }
        acc.commit().await.unwrap();
        for key in vec!["b", "bb", "bbb"] {
            acc.set_value(key.to_owned(), Value::Boolval(true)).await.unwrap();
        }

        let (get_iterator, server_end) = create_proxy().unwrap();
        acc.get_prefix("".to_string(), server_end).await.unwrap();

        let res = drain_stash_iterator(|| get_iterator.get_next()).await;
        let mut res: Vec<String> = res.iter().map(|kv| kv.key.clone()).collect();

        res.sort_unstable();
        assert_eq!(vec!["a", "aa", "aaa", "b", "bb", "bbb"], res);
    }
}
