text: #pragma once
  
  #include <internal/facts/linux/processor_resolver.hpp>
  #include <map>
  #include <functional>
  #include <vector>
  #include <tuple>
  #include <memory>
  #include <boost/filesystem.hpp>
  #include <boost/optional.hpp>
  #include <boost/nowide/iostream.hpp>
  #include <boost/nowide/fstream.hpp>
  
  struct linux_cpu_fixture
  {
      explicit linux_cpu_fixture(boost::filesystem::path const& sys_dir, int id, std::string const& model_name);
  
      void set_logical_id(std::string const& logical_id);
      virtual void set_physical_id(std::string const& physical_id);
      virtual void set_speed(int64_t speed);
      void set_info(std::string const& key, std::string const& value);
      void erase_info(std::string const& key);
      void erase_all_info();
      std::string get_info();
  
  protected:
      virtual void init_info(std::string const& model_name);
  
      std::map<std::string, std::string, std::function<bool(std::string const&, std::string const&)>> _info;
  
      boost::filesystem::path _cpuroot;
      boost::filesystem::path _topology;
      boost::filesystem::path _cpufreq;
  };
  
  struct linux_power_cpu_fixture : linux_cpu_fixture
  {
      explicit linux_power_cpu_fixture(boost::filesystem::path const& sys_dir, int id, std::string const& model_name);
  
      virtual void set_physical_id(std::string const& physical_id) override;
      virtual void set_speed(int64_t speed) override;
  
  protected:
      virtual void init_info(std::string const& model_name) override;
  };
  
  struct test_linux_processor_resolver : facter::facts::linux::processor_resolver
  {
      using facter::facts::linux::processor_resolver::ArchitectureType;
      struct test_linux_data : facter::facts::resolvers::processor_resolver::data {};
      test_linux_data collect_cpu_data(std::string const& root);
      ArchitectureType architecture_type(test_linux_data const& data, std::string const& root);
  };
  
  struct linux_processor_fixture
  {
      explicit linux_processor_fixture(std::string const& root, test_linux_processor_resolver::ArchitectureType arch_type);
      ~linux_processor_fixture();
      int add_cpu(std::string const& model_name);
      linux_cpu_fixture& get_cpu(int id);
      void write_cpuinfo();
      void add_to_sys_dir(std::string const& dir_name);
      void clear_sys_dir();
      void reset(test_linux_processor_resolver::ArchitectureType arch_type = test_linux_processor_resolver::ArchitectureType::X86);
  
  private:
      std::vector<std::unique_ptr<linux_cpu_fixture>> _cpus;
      std::function<linux_cpu_fixture*(boost::filesystem::path const&, int, std::string const&)> make_cpu;
      int _next_id;
  
      boost::filesystem::path _root;
      boost::filesystem::path _proc;
      boost::filesystem::path _sys;
  };
  
  // a cpu is defined as (Model name, Logical id, Physical id, (Optional) Speed)
  std::vector<int> setup_linux_processor_fixture(linux_processor_fixture& fixture, std::vector<std::tuple<std::string, std::string, std::string, boost::optional<int64_t>>> const& cpu_params);
  