US_END_NAMESPACE


void TestServiceFactoryModuleScope()
{

  // Install and start test module H, a service factory and test that the methods
  // in that interface works.

  SharedLibrary target(LIB_PATH, "TestModuleH");

#ifdef US_BUILD_SHARED_LIBS
  try
  {
    target.Load();
  }
  catch (const std::exception& e)
  {
    US_TEST_FAILED_MSG( << "Failed to load module, got exception: " << e.what())
  }
#endif

  Module* moduleH = ModuleRegistry::GetModule("TestModuleH");
  US_TEST_CONDITION_REQUIRED(moduleH != 0, "Test for existing module TestModuleH")

  std::vector<ServiceReferenceU> registeredRefs = moduleH->GetRegisteredServices();
  US_TEST_CONDITION_REQUIRED(registeredRefs.size() == 2, "# of registered services")
  US_TEST_CONDITION(registeredRefs[0].GetProperty(ServiceConstants::SERVICE_SCOPE()).ToString() == ServiceConstants::SCOPE_MODULE(), "service scope")
  US_TEST_CONDITION(registeredRefs[1].GetProperty(ServiceConstants::SERVICE_SCOPE()).ToString() == ServiceConstants::SCOPE_PROTOTYPE(), "service scope")

  ModuleContext* mc = GetModuleContext();
  // Check that a service reference exist
  const ServiceReferenceU sr1 = mc->GetServiceReference("us::TestModuleH");
  US_TEST_CONDITION_REQUIRED(sr1, "Service shall be present.")
  US_TEST_CONDITION(sr1.GetProperty(ServiceConstants::SERVICE_SCOPE()).ToString() == ServiceConstants::SCOPE_MODULE(), "service scope")

  InterfaceMap service = mc->GetService(sr1);
  US_TEST_CONDITION_REQUIRED(service.size() >= 1, "GetService()")
  InterfaceMap::const_iterator serviceIter = service.find("us::TestModuleH");
  US_TEST_CONDITION_REQUIRED(serviceIter != service.end(), "GetService()")
  US_TEST_CONDITION_REQUIRED(serviceIter->second != nullptr, "GetService()")

  InterfaceMap service2 = mc->GetService(sr1);
  US_TEST_CONDITION(service == service2, "Same service pointer")

  std::vector<ServiceReferenceU> usedRefs = mc->GetModule()->GetServicesInUse();
  US_TEST_CONDITION_REQUIRED(usedRefs.size() == 1, "services in use")
  US_TEST_CONDITION(usedRefs[0] == sr1, "service ref in use")

  InterfaceMap service3 = moduleH->GetModuleContext()->GetService(sr1);
  US_TEST_CONDITION(service != service3, "Different service pointer")
  US_TEST_CONDITION(moduleH->GetModuleContext()->UngetService(sr1), "UngetService()")

  US_TEST_CONDITION_REQUIRED(mc->UngetService(sr1) == false, "ungetService()")
  US_TEST_CONDITION_REQUIRED(mc->UngetService(sr1) == true, "ungetService()")

  target.Unload();
}
InterfaceMap ServiceReferenceBasePrivate::GetServiceFromFactory(Module* module,
                                                                ServiceFactory* factory,
                                                                bool isModuleScope)
{
  assert(factory && "Factory service pointer is nullptr");
  InterfaceMap s;
  try
  {
    InterfaceMap smap = factory->GetService(module,
                                            ServiceRegistrationBase(registration));
    if (smap.empty())
    {
      US_WARN << "ServiceFactory produced null";
      return smap;
    }
    const std::vector<std::string>& classes =
        ref_any_cast<std::vector<std::string> >(registration->properties.Value(ServiceConstants::OBJECTCLASS()));
    for (std::vector<std::string>::const_iterator i = classes.begin();
         i != classes.end(); ++i)
    {
      if (smap.find(*i) == smap.end() && *i != "org.cppmicroservices.factory")
      {
        US_WARN << "ServiceFactory produced an object "
                   "that did not implement: " << (*i);
        smap.clear();
        return smap;
      }
    }
    s = smap;

    if (isModuleScope)
    {
      registration->moduleServiceInstance.insert(std::make_pair(module, smap));
    }
    else
    {
      registration->prototypeServiceInstances[module].push_back(smap);
    }
  }
  catch (...)
  {
    US_WARN << "ServiceFactory threw an exception";
    s.clear();
  }
  return s;
}