File indexing completed on 2026-10-08 08:36:30
0001 """Offline bootstrap tests. No BNL access, downloads, builds or submissions.
0002
0003 Run: python3 -m unittest discover -s tools/tests -v
0004 Tests of sourced setup use real tcsh when it is installed; otherwise skip.
0005 """
0006 from pathlib import Path
0007 import os
0008 import shutil
0009 import subprocess
0010 import tempfile
0011 import unittest
0012
0013 TOOLS = Path(__file__).resolve().parents[1]
0014 BOOTSTRAP = TOOLS / "bootstrap-yall-integration.sh"
0015 TCSH = shutil.which("tcsh")
0016
0017
0018 def executable(path, text):
0019 path.parent.mkdir(parents=True, exist_ok=True)
0020 path.write_text("#!/bin/bash\nset -eu\n" + text, encoding="utf-8")
0021 path.chmod(0o755)
0022
0023
0024 class BootstrapTest(unittest.TestCase):
0025 def setUp(self):
0026 self.temp = tempfile.TemporaryDirectory()
0027 self.addCleanup(self.temp.cleanup)
0028 self.root = Path(self.temp.name)
0029 self.workspace = self.root / "my-workspace"
0030 self.workspace.mkdir()
0031 self.bin = self.root / "host-bin"
0032 self.bin.mkdir()
0033 self.userbase = self.root / "user-install"
0034 self.log = self.root / "calls.log"
0035 self.repo = self.workspace / "epic-lfhcal-tbana"
0036 for checkout in (self.repo, self.workspace / "yall-run"):
0037 (checkout / ".git").mkdir(parents=True)
0038 executable(self.bin / "git", 'printf "git %s\\n" "$*" >> "$TEST_LOG"\n')
0039 executable(self.bin / "curl", 'echo "unexpected download" >&2; exit 99\n')
0040 executable(self.bin / "tcsh", 'printf "tcsh %s\\n" "$*" >> "$TEST_LOG"\nexit "${TEST_TCSH_RC:-0}"\n')
0041 executable(self.bin / "python3", '''printf "python3 %s\\n" "$*" >> "$TEST_LOG"
0042 if [[ "$*" == "-m site --user-base" ]]; then
0043 echo "$TEST_USERBASE"
0044 elif [[ "$*" != "-m pip install --user -e "* ]]; then
0045 echo "unexpected python invocation: $*" >&2
0046 exit 99
0047 fi
0048 ''')
0049 for cmd in ("condor_submit", "condor_submit_dag"):
0050 executable(self.bin / cmd, 'echo "unexpected submission" >&2; exit 99\n')
0051 executable(self.userbase / "bin/yall-run", '[[ "$*" == "--help" ]]\n')
0052 executable(self.workspace / "eic-shell", 'exit 0\n')
0053 executable(self.repo / "tools/run-in-eic-shell.sh", '''printf "wrapper %s\\n" "$*" >> "$TEST_LOG"
0054 [[ "$1" == "$TEST_WORKSPACE/eic-shell" ]]
0055 shift
0056 if [[ "$1" == cmake && "$2" == --build ]]; then
0057 mkdir -p "$3"
0058 for exe in Convert DataPrep; do
0059 printf '#!/bin/sh\\nexit 0\\n' > "$3/$exe"
0060 chmod +x "$3/$exe"
0061 done
0062 elif [[ "$*" == "root-config --version" ]]; then
0063 echo "mock-ROOT"
0064 fi
0065 ''')
0066 self.env = {k: v for k, v in os.environ.items()
0067 if not k.startswith(("LFHCAL_", "YALL_", "EIC_"))}
0068 self.env.update(PATH=f"{self.bin}:{os.environ['PATH']}",
0069 TEST_LOG=str(self.log), TEST_USERBASE=str(self.userbase),
0070 TEST_WORKSPACE=str(self.workspace))
0071
0072 def run_install(self):
0073 return subprocess.run(["bash", str(BOOTSTRAP)], cwd=self.workspace,
0074 env=self.env, capture_output=True, text=True)
0075
0076 def install_ok(self):
0077 result = self.run_install()
0078 self.assertEqual(result.returncode, 0, result.stdout + result.stderr)
0079 return result
0080
0081 def test_syntax(self):
0082 subprocess.run(["bash", "-n", str(BOOTSTRAP)], check=True)
0083
0084 def test_tcsh_only_generation_and_bnl_defaults(self):
0085 self.install_ok()
0086 site = (self.workspace / "site-env.tcsh").read_text()
0087 activate = (self.workspace / "activate.tcsh").read_text()
0088 self.assertIn('/gpfs01/star/pwg/pnord/eic/2026TBdata', site)
0089 self.assertNotIn('/gpfs/mnt', site)
0090 self.assertIn('/gpfs01/star/scratch/`id -un`/lfhcal', site)
0091 self.assertIn('mkdir -p "$LFHCAL_WORK/campaigns"', activate)
0092 self.assertIn('! -r "$LFHCAL_DATA"', activate)
0093 self.assertNotIn('mkdir -p "$LFHCAL_DATA"', activate)
0094 self.assertFalse((self.workspace / "activate.sh").exists())
0095 self.assertFalse((self.workspace / "site-env.sh").exists())
0096 self.assertFalse((self.workspace / "data").exists())
0097 self.assertFalse((self.workspace / "work").exists())
0098 self.assertFalse((self.workspace / ".venv-yall").exists())
0099
0100 def test_existing_settings_and_old_generated_files_preserved(self):
0101 custom = 'setenv LFHCAL_DATA /existing/raw\nsetenv LFHCAL_WORK /existing/work\n'
0102 (self.workspace / "site-env.tcsh").write_text(custom)
0103 (self.workspace / "site-env.sh").write_text("# user edits, preserve\n")
0104 self.install_ok()
0105 self.assertEqual((self.workspace / "site-env.tcsh").read_text(), custom)
0106 self.assertEqual((self.workspace / "site-env.sh").read_text(), "# user edits, preserve\n")
0107
0108 def test_host_user_install_container_build_no_submission(self):
0109 self.install_ok()
0110 log = self.log.read_text()
0111 self.assertIn(f'python3 -m pip install --user -e {self.workspace}/yall-run', log)
0112 self.assertIn('submodule update --init --recursive', log)
0113 self.assertIn('cmake --build', log)
0114 self.assertNotIn('venv', log)
0115 self.assertNotIn('pip install --upgrade', log)
0116 self.assertNotIn('condor_submit', log)
0117
0118 def test_scratch_setup_failure_stops_before_install_or_build(self):
0119 self.env['TEST_TCSH_RC'] = '1'
0120 result = self.run_install()
0121 self.assertNotEqual(result.returncode, 0)
0122 self.assertNotIn('pip install', self.log.read_text())
0123 self.assertNotIn('cmake', self.log.read_text())
0124
0125 def test_current_folder_wins_over_old_environment(self):
0126 self.env['LFHCAL_HOME'] = str(self.root / 'old-install')
0127 self.install_ok()
0128 text = (self.workspace / "activate.tcsh").read_text()
0129 self.assertIn(f'setenv LFHCAL_HOME "{self.workspace}"', text)
0130 self.assertFalse((self.root / 'old-install').exists())
0131
0132 def test_parent_directories_created_by_generated_mkdir(self):
0133
0134 self.install_ok()
0135 activation = (self.workspace / 'activate.tcsh').read_text()
0136 mkdir = next(line.strip() for line in activation.splitlines()
0137 if line.strip().startswith('mkdir -p '))
0138 scratch = self.root / 'scratch' / 'new-user' / 'lfhcal'
0139 env = dict(self.env, LFHCAL_WORK=str(scratch))
0140 subprocess.run(['bash', '-c', mkdir], env=env, check=True)
0141 self.assertTrue((scratch / 'campaigns').is_dir())
0142 marker = scratch / 'keep-me'
0143 marker.write_text('earlier output')
0144 subprocess.run(['bash', '-c', mkdir], env=env, check=True)
0145 self.assertEqual(marker.read_text(), 'earlier output')
0146
0147 @unittest.skipUnless(TCSH, 'tcsh is not installed')
0148 def test_real_tcsh_source_creates_scratch_and_leaves_input_unchanged(self):
0149 self.install_ok()
0150 raw = self.root / 'raw'
0151 raw.mkdir()
0152 (raw / 'Run296.h2g').write_text('unchanged')
0153 scratch = self.root / 'scratch' / 'new-user' / 'lfhcal'
0154 env = dict(self.env, LFHCAL_DATA=str(raw), LFHCAL_WORK=str(scratch))
0155 result = subprocess.run([TCSH, '-f', str(self.workspace / 'activate.tcsh')],
0156 env=env, text=True, capture_output=True)
0157 self.assertEqual(result.returncode, 0, result.stdout + result.stderr)
0158 self.assertTrue((scratch / 'campaigns').is_dir())
0159 self.assertEqual([p.name for p in raw.iterdir()], ['Run296.h2g'])
0160
0161 @unittest.skipUnless(TCSH, 'tcsh is not installed')
0162 def test_real_tcsh_work_failure_returns_error(self):
0163 self.install_ok()
0164 blocker = self.root / 'not-a-directory'
0165 blocker.write_text('keep')
0166 env = dict(self.env, LFHCAL_DATA=str(self.root),
0167 LFHCAL_WORK=str(blocker / 'lfhcal'))
0168 result = subprocess.run([TCSH, '-f', str(self.workspace / 'activate.tcsh')],
0169 env=env, text=True, capture_output=True)
0170 self.assertNotEqual(result.returncode, 0, result.stdout + result.stderr)
0171 self.assertEqual(blocker.read_text(), 'keep')
0172
0173
0174 if __name__ == '__main__':
0175 unittest.main()