Skip to content

Unit tests depend on the global PARAM singleton #7629

Description

@Critsium-xy

Describe the Code Quality Issue

A large number of unit tests directly reference and mutate the global singleton PARAM (extern Parameter PARAM, declared in source/source_io/module_parameter/parameter.h:50). Unit tests should not depend on global program state, but this pattern is pervasive across almost every module.

Parameter is deliberately designed to be read-only to the rest of the program:

class Parameter {
  public:
    // We can only read the value of input, but cannot modify it.
    const Input_para& inp = input;
    const MD_para&     mdp = input.mdp;
    const System_para& globalv = sys;
    ...
  private:
    // Only ReadInput and CalAtomInfo can modify the value of Parameter.
    // Do not add extra friend class here!!!
    friend class ModuleIO::ReadInput;
    friend class CalAtomsInfo;

    Input_para  input;   // private
    System_para sys;     // private
};
extern Parameter PARAM;

The data members input and sys are private, and only two friend classes are allowed to modify them — the header explicitly warns Do not add extra friend class here!!!.

Additional Context

Despite this, unit tests bypass the design in two compounding ways:

  1. Global-state dependency. Tests read from and write to the global PARAM in their SetUp() in order to drive the code under test. This makes tests order-dependent, non-hermetic, and hard to parallelize, because one test's mutation of PARAM leaks into others through a process-wide singleton.

  2. Encapsulation breakage via #define private public. Because input/sys are private, tests that need to set configuration (PARAM.input.xxx = ..., PARAM.sys.xxx = ...) resort to #define private public before including headers, defeating the access control the class was built to enforce.

Scale of the problem:

Metric Count
Test files referencing PARAM 78 .cpp + 1 .h
Total PARAM references in tests ~1356
PARAM.input.* accesses (writes to private member) 1149
PARAM.sys.* accesses (writes to private member) 181
PARAM.globalv / PARAM.mdp (read-only interface) 31
Test files using #define private public 93

Affected files

source_estate (most affected)
File Refs
source/source_estate/test/charge_mixing_test.cpp 325
source/source_estate/test/elecstate_base_test.cpp 67
source/source_estate/test/elecstate_print_test.cpp 40
source/source_estate/test/potential_new_test.cpp 25
source/source_estate/test/charge_extra_test.cpp 24
source/source_estate/test/elecstate_energy_test.cpp 20
source/source_estate/test/charge_test.cpp 19
source/source_estate/test/elecstate_pw_test.cpp 16
source/source_estate/test/elecstate_magnetism_test.cpp 12
source/source_estate/test_mpi/charge_mpi_test.cpp 7
source/source_estate/test/elecstate_occupy_test.cpp 3
source_cell
File Refs
source/source_cell/test/unitcell_test.cpp 99
source/source_cell/test/unitcell_test_readpp.cpp 88
source/source_cell/test/klist_test.cpp 68
source/source_cell/test/unitcell_test_para.cpp 12
source/source_cell/module_neighbor/test/sltk_grid_test.cpp 7
source/source_cell/test/pseudo_nc_test.cpp 5
source/source_cell/test/read_pp_test.cpp 5
source/source_cell/test_pw/unitcell_test_pw.cpp 4
source/source_cell/test/unitcell_test_setupcell.cpp 4
source/source_cell/test/atom_pseudo_test.cpp 4
source/source_cell/test/klist_test_para.cpp 4
source/source_cell/module_neighbor/test/sltk_atom_arrange_test.cpp 3
source/source_cell/test/read_atoms_helper_test.cpp 1
source/source_cell/test/atom_spec_test.cpp 1
source_io
File Refs
source/source_io/test/to_qo_test.cpp 148
source/source_io/test/print_info_test.cpp 28
source/source_io/test/read_wfc_pw_test.cpp 19
source/source_io/test/write_wfc_nao_test.cpp 14
source/source_io/test/write_dos_pw_test.cpp 14
source/source_io/test/write_hs_r_compat_test.cpp 12
source/source_io/module_json/test/para_json_test.cpp 8
source/source_io/test/read_wf2rho_pw_test.cpp 8
source/source_io/test/write_eig_occ_test.cpp 8
source/source_io/test/write_orb_info_test.cpp 7
source/source_io/test/read_wfc_nao_test.cpp 4
source/source_io/test_serial/read_input_test.cpp 3
source/source_io/test/outputlog_test.cpp 3
source/source_io/test/read_rhog_test.cpp 3
source/source_io/test/read_input_ptest.cpp 2
source/source_io/module_dm/test/write_dmk_test.cpp 2
source/source_io/test/single_R_io_test.cpp 1
source_hsolver
File Refs
source/source_hsolver/test/test_hsolver_pw.cpp 14
source/source_hsolver/test/test_hsolver_sdft.cpp 5
source/source_hsolver/test/diago_pexsi_test.cpp 4
source/source_hsolver/test/diago_lcao_test.cpp 2
source/source_hsolver/test/diago_lcao_cusolver_test.cpp 2
source/source_hsolver/test/diago_lapack_test.cpp 2
source/source_hsolver/test/diago_cg_test.cpp 2
source/source_hsolver/test/diago_cg_real_test.cpp 2
source/source_hsolver/test/diago_cg_float_test.cpp 2
source_relax
File Refs
source/source_relax/test/lattice_change_basic_test.cpp 15
source/source_relax/test/ions_move_bfgs_test.cpp 15
source/source_relax/test/ions_move_basic_test.cpp 9
source/source_relax/test/relax_test.cpp 5
source/source_relax/test/ions_move_sd_test.cpp 4
source/source_relax/test/bfgs_basic_test.cpp 3
source/source_relax/test/ions_move_cg_test.cpp 1
source/source_relax/test/bfgs_test.cpp 1
source_md
File Refs
source/source_md/test/verlet_test.cpp 3
source/source_md/test/nhchain_test.cpp 3
source/source_md/test/msst_test.cpp 3
source/source_md/test/langevin_test.cpp 3
source/source_md/test/fire_test.cpp 3
source/source_md/test/md_func_test.cpp 2
source/source_md/test/setcell.h 5 (header)
source_lcao
File Refs
source/source_lcao/module_deepks/test/deepks_test_prep.cpp 6
source/source_lcao/module_dftu/test/dftu_pw_test.cpp 3
source/source_lcao/module_operator_lcao/test/test_dftu.cpp 3
source/source_lcao/module_rt/test/propagator_test1.cpp 2
source/source_lcao/module_rt/test/propagator_test2.cpp 2
source/source_lcao/module_rt/test/propagator_test3.cpp 2
source/source_lcao/module_deepks/test/deepks_test_edelta.cpp 1
Other modules
File Refs
source/source_psi/test/psi_initializer_unit_test.cpp 50
source/source_base/libm/test/libm_test.cpp 29
source/source_hamilt/module_surchem/test/cal_vel_test.cpp 2
source/source_basis/module_ao/test/ORB_atomic_lm_test.cpp 2
source/source_basis/module_ao/test/ORB_nonlocal_lm_test.cpp 1
source/source_pw/module_pwdft/test/structure_factor_test.cpp 1

Task list for Issue attackers (only for developers)

  • Identify the specific code file or section with the code quality issue.
  • Investigate the issue and determine the root cause.
  • Research best practices and potential solutions for the identified issue.
  • Refactor the code to improve code quality, following the suggested solution.
  • Ensure the refactored code adheres to the project's coding standards.
  • Test the refactored code to ensure it functions as expected.
  • Update any relevant documentation, if necessary.
  • Submit a pull request with the refactored code and a description of the changes made.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions