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

#include "multiprocess_func_list.h"

#include <map>

// Helper functions to maintain mapping of "test name"->test func.
// The information is accessed via a global map.
namespace multi_process_function_list {

namespace {

struct ProcessFunctions {
  ProcessFunctions() : main(NULL), setup(NULL) {}
  ProcessFunctions(TestMainFunctionPtr main, SetupFunctionPtr setup)
      : main(main),
        setup(setup) {
  }
  TestMainFunctionPtr main;
  SetupFunctionPtr setup;
};

typedef std::map<std::string, ProcessFunctions> MultiProcessTestMap;

// Retrieve a reference to the global 'func name' -> func ptr map.
MultiProcessTestMap& GetMultiprocessFuncMap() {
  static MultiProcessTestMap test_name_to_func_ptr_map;
  return test_name_to_func_ptr_map;
}

}  // namespace

AppendMultiProcessTest::AppendMultiProcessTest(
    std::string test_name,
    TestMainFunctionPtr main_func_ptr,
    SetupFunctionPtr setup_func_ptr) {
  GetMultiprocessFuncMap()[test_name] =
      ProcessFunctions(main_func_ptr, setup_func_ptr);
}

int InvokeChildProcessTest(const std::string& test_name) {
  MultiProcessTestMap& func_lookup_table = GetMultiprocessFuncMap();
  MultiProcessTestMap::iterator it = func_lookup_table.find(test_name);
  if (it != func_lookup_table.end()) {
    const ProcessFunctions& process_functions = it->second;
    if (process_functions.setup)
      (*process_functions.setup)();
    if (process_functions.main)
      return (*process_functions.main)();
  }

  return -1;
}

}  // namespace multi_process_function_list
