def test_alt_conditions(runner, paths, tst_sys, tst_distro, tst_host, tst_user, suffix): """Test conditions supported by yadm alt""" yadm_dir = setup_standard_yadm_dir(paths) # set the class tst_class = 'testclass' utils.set_local(paths, 'class', tst_class) suffix = string.Template(suffix).substitute( tst_sys=tst_sys, tst_distro=tst_distro, tst_class=tst_class, tst_host=tst_host, tst_user=tst_user, ) utils.create_alt_files(paths, suffix) run = runner([paths.pgm, '-Y', yadm_dir, 'alt']) assert run.success assert run.err == '' linked = utils.parse_alt_output(run.out) for link_path in TEST_PATHS: source_file = link_path + suffix assert paths.work.join(link_path).islink() target = py.path.local(os.path.realpath(paths.work.join(link_path))) if target.isfile(): assert paths.work.join(link_path).read() == source_file assert str(paths.work.join(source_file)) in linked else: assert paths.work.join(link_path).join( utils.CONTAINED).read() == source_file assert str(paths.work.join(source_file)) in linked
def test_delimiter(runner, yadm_y, paths, tst_sys, tst_host, tst_user, delimiter): """Test delimiters used""" suffix = '##' + delimiter.join([tst_sys, tst_host, tst_user]) # create file utils.create_alt_files(paths, suffix) # run alt to trigger linking run = runner(yadm_y('alt')) assert run.success assert run.err == '' linked = linked_list(run.out) # assert the proper linking has occurred # only a delimiter of '.' is valid for file_path in TEST_PATHS: source_file = file_path + suffix if delimiter == '.': assert paths.work.join(file_path).islink() target = py.path.local(paths.work.join(file_path).readlink()) if target.isfile(): assert paths.work.join(file_path).read() == source_file assert str(paths.work.join(source_file)) in linked else: assert paths.work.join(file_path).join( utils.CONTAINED).read() == source_file assert str(paths.work.join(source_file)) in linked else: assert not paths.work.join(file_path).exists() assert str(paths.work.join(source_file)) not in linked
def test_auto_alt(runner, yadm_y, paths, autoalt): """Test setting auto-alt""" # set the value of auto-alt if autoalt: os.system(' '.join(yadm_y('config', 'yadm.auto-alt', autoalt))) # create file suffix = '##' utils.create_alt_files(paths, suffix) # run status to possibly trigger linking run = runner(yadm_y('status')) assert run.success assert run.err == '' linked = linked_list(run.out) # assert the proper linking has occurred for file_path in TEST_PATHS: source_file = file_path + suffix if autoalt == 'false': assert not paths.work.join(file_path).exists() else: assert paths.work.join(file_path).islink() target = py.path.local(paths.work.join(file_path).readlink()) if target.isfile(): assert paths.work.join(file_path).read() == source_file # no linking output when run via auto-alt assert str(paths.work.join(source_file)) not in linked else: assert paths.work.join(file_path).join( utils.CONTAINED).read() == source_file # no linking output when run via auto-alt assert str(paths.work.join(source_file)) not in linked
def test_local_override(runner, yadm_y, paths, tst_distro, envtpl_present): """Test local overrides""" if not envtpl_present: pytest.skip('Unable to test without envtpl.') # define local overrides utils.set_local(paths, 'class', 'or-class') utils.set_local(paths, 'hostname', 'or-hostname') utils.set_local(paths, 'os', 'or-os') utils.set_local(paths, 'user', 'or-user') template = ('j2-{{ YADM_CLASS }}-' '{{ YADM_OS }}-{{ YADM_HOSTNAME }}-' '{{ YADM_USER }}-{{ YADM_DISTRO }}') expected = f'j2-or-class-or-os-or-hostname-or-user-{tst_distro}' utils.create_alt_files(paths, '##yadm.j2', content=template) # run alt to trigger linking run = runner(yadm_y('alt')) assert run.success assert run.err == '' created = created_list(run.out) # assert the proper creation has occurred for file_path in (utils.ALT_FILE1, utils.ALT_FILE2): source_file = file_path + '##yadm.j2' assert paths.work.join(file_path).isfile() lines = paths.work.join(file_path).readlines(cr=False) assert lines[0] == source_file assert lines[1] == expected assert str(paths.work.join(source_file)) in created
def test_local_override(runner, yadm_y, paths, tst_sys, tst_host, tst_user): """Test local overrides""" # define local overrides utils.set_local(paths, 'class', 'or-class') utils.set_local(paths, 'hostname', 'or-hostname') utils.set_local(paths, 'os', 'or-os') utils.set_local(paths, 'user', 'or-user') # create files, the first would normally be the most specific version # however, the second is the overridden version which should be preferred. utils.create_alt_files( paths, f'##or-class.{tst_sys}.{tst_host}.{tst_user}') utils.create_alt_files( paths, '##or-class.or-os.or-hostname.or-user') # run alt to trigger linking run = runner(yadm_y('alt')) assert run.success assert run.err == '' linked = linked_list(run.out) # assert the proper linking has occurred for file_path in TEST_PATHS: source_file = file_path + '##or-class.or-os.or-hostname.or-user' assert paths.work.join(file_path).islink() target = py.path.local(paths.work.join(file_path).readlink()) if target.isfile(): assert paths.work.join(file_path).read() == source_file assert str(paths.work.join(source_file)) in linked else: assert paths.work.join(file_path).join( utils.CONTAINED).read() == source_file assert str(paths.work.join(source_file)) in linked
def test_class_case(runner, yadm_y, paths, tst_sys, suffix): """Test range of class cases""" # set the class utils.set_local(paths, 'class', suffix) # create files endings = [suffix] if tst_sys == 'Linux': # Only create all of these side-by-side on Linux, which is # unquestionably case-sensitive. This would break tests on # case-insensitive systems. endings = ['AAA', 'ZZZ', 'aaa', 'zzz'] for ending in endings: utils.create_alt_files(paths, f'##{ending}') # run alt to trigger linking run = runner(yadm_y('alt')) assert run.success assert run.err == '' linked = linked_list(run.out) # assert the proper linking has occurred for file_path in TEST_PATHS: source_file = file_path + f'##{suffix}' assert paths.work.join(file_path).islink() target = py.path.local(paths.work.join(file_path).readlink()) if target.isfile(): assert paths.work.join(file_path).read() == source_file assert str(paths.work.join(source_file)) in linked else: assert paths.work.join(file_path).join( utils.CONTAINED).read() == source_file assert str(paths.work.join(source_file)) in linked
def test_auto_alt(runner, yadm_y, paths, autoalt, tst_sys, envtpl_present): """Test setting auto-alt""" if not envtpl_present: pytest.skip('Unable to test without envtpl.') # set the value of auto-alt if autoalt: os.system(' '.join(yadm_y('config', 'yadm.auto-alt', autoalt))) # create file jinja_suffix = '##yadm.j2' utils.create_alt_files(paths, jinja_suffix, content='{{ YADM_OS }}') # run status to possibly trigger linking env = os.environ.copy() env['YADM_COMPATIBILITY'] = '1' run = runner(yadm_y('status'), env=env) assert run.success assert run.err == '' created = utils.parse_alt_output(run.out, linked=False) # assert the proper creation has occurred for file_path in (utils.ALT_FILE1, utils.ALT_FILE2): source_file = file_path + jinja_suffix if autoalt == 'false': assert not paths.work.join(file_path).exists() else: assert paths.work.join(file_path).isfile() lines = paths.work.join(file_path).readlines(cr=False) assert lines[0] == source_file assert lines[1] == tst_sys # no created output when run via auto-alt assert str(paths.work.join(source_file)) not in created
def test_relative_link(runner, paths, yadm_alt): """Confirm links created are relative""" yadm_dir = setup_standard_yadm_dir(paths) utils.create_alt_files(paths, '##default', tracked=True, encrypt=False, exclude=False, yadm_alt=yadm_alt, yadm_dir=yadm_dir) run = runner([paths.pgm, '-Y', yadm_dir, 'alt']) assert run.success assert run.err == '' basepath = yadm_dir.join('alt') if yadm_alt else paths.work for link_path in TEST_PATHS: source_file_content = link_path + '##default' source_file = basepath.join(source_file_content) link_file = paths.work.join(link_path) link = link_file.readlink() relpath = os.path.relpath(source_file, start=os.path.dirname(link_file)) assert link == relpath
def test_alt_source(runner, paths, tracked, encrypt, exclude, yadm_alt): """Test yadm alt operates on all expected sources of alternates""" yadm_dir = setup_standard_yadm_dir(paths) utils.create_alt_files(paths, '##default', tracked=tracked, encrypt=encrypt, exclude=exclude, yadm_alt=yadm_alt, yadm_dir=yadm_dir) run = runner([paths.pgm, '-Y', yadm_dir, 'alt']) assert run.success assert run.err == '' linked = utils.parse_alt_output(run.out) basepath = yadm_dir.join('alt') if yadm_alt else paths.work for link_path in TEST_PATHS: source_file_content = link_path + '##default' source_file = basepath.join(source_file_content) link_file = paths.work.join(link_path) if tracked or (encrypt and not exclude): assert link_file.islink() target = py.path.local(os.path.realpath(link_file)) if target.isfile(): assert link_file.read() == source_file_content assert str(source_file) in linked else: assert link_file.join( utils.CONTAINED).read() == source_file_content assert str(source_file) in linked else: assert not link_file.exists() assert str(source_file) not in linked
def test_auto_alt(runner, yadm_y, paths, autoalt): """Test auto alt""" # set the value of auto-alt if autoalt: os.system(' '.join(yadm_y('config', 'yadm.auto-alt', autoalt))) utils.create_alt_files(paths, '##default') run = runner(yadm_y('status')) assert run.success assert run.err == '' linked = utils.parse_alt_output(run.out) for link_path in TEST_PATHS: source_file = link_path + '##default' if autoalt == 'false': assert not paths.work.join(link_path).exists() else: assert paths.work.join(link_path).islink() target = py.path.local(os.path.realpath( paths.work.join(link_path))) if target.isfile(): assert paths.work.join(link_path).read() == source_file # no linking output when run via auto-alt assert str(paths.work.join(source_file)) not in linked else: assert paths.work.join(link_path).join( utils.CONTAINED).read() == source_file # no linking output when run via auto-alt assert str(paths.work.join(source_file)) not in linked
def test_alt(runner, yadm_y, paths, tst_sys, tst_host, tst_user, tracked, encrypt, exclude, precedence_index): """Test alternate linking This test is done by iterating for the number of templates in PRECEDENCE. With each iteration, another file is left off the list. So with each iteration, the template with the "highest precedence" is left out. The file using the highest precedence should be the one linked. """ # set the class tst_class = 'testclass' utils.set_local(paths, 'class', tst_class) # process the templates in PRECEDENCE precedence = list() for template in PRECEDENCE: precedence.append( string.Template(template).substitute( tst_class=tst_class, tst_host=tst_host, tst_sys=tst_sys, tst_user=tst_user, )) # create files using a subset of files for suffix in precedence[0:precedence_index + 1]: utils.create_alt_files(paths, suffix, tracked=tracked, encrypt=encrypt, exclude=exclude) # run alt to trigger linking env = os.environ.copy() env['YADM_COMPATIBILITY'] = '1' run = runner(yadm_y('alt'), env=env) assert run.success assert run.err == '' linked = utils.parse_alt_output(run.out) # assert the proper linking has occurred for file_path in TEST_PATHS: source_file = file_path + precedence[precedence_index] if tracked or (encrypt and not exclude): assert paths.work.join(file_path).islink() target = py.path.local(os.path.realpath( paths.work.join(file_path))) if target.isfile(): assert paths.work.join(file_path).read() == source_file assert str(paths.work.join(source_file)) in linked else: assert paths.work.join(file_path).join( utils.CONTAINED).read() == source_file assert str(paths.work.join(source_file)) in linked else: assert not paths.work.join(file_path).exists() assert str(paths.work.join(source_file)) not in linked
def test_jinja(runner, yadm_y, paths, tst_sys, tst_host, tst_user, tst_distro, tracked, encrypt, exclude, envtpl_present): """Test jinja processing""" if not envtpl_present: pytest.skip('Unable to test without envtpl.') jinja_suffix = '##yadm.j2' # set the class tst_class = 'testclass' utils.set_local(paths, 'class', tst_class) template = ('j2-{{ YADM_CLASS }}-' '{{ YADM_OS }}-{{ YADM_HOSTNAME }}-' '{{ YADM_USER }}-{{ YADM_DISTRO }}' '-{%- ' f"include '{utils.INCLUDE_FILE}'" ' -%}') expected = (f'j2-{tst_class}-' f'{tst_sys}-{tst_host}-' f'{tst_user}-{tst_distro}' f'-{utils.INCLUDE_CONTENT}') utils.create_alt_files(paths, jinja_suffix, content=template, tracked=tracked, encrypt=encrypt, exclude=exclude, includefile=True) # run alt to trigger linking env = os.environ.copy() env['YADM_COMPATIBILITY'] = '1' run = runner(yadm_y('alt'), env=env) assert run.success assert run.err == '' created = utils.parse_alt_output(run.out, linked=False) # assert the proper creation has occurred for file_path in (utils.ALT_FILE1, utils.ALT_FILE2): source_file = file_path + jinja_suffix if tracked or (encrypt and not exclude): assert paths.work.join(file_path).isfile() lines = paths.work.join(file_path).readlines(cr=False) assert lines[0] == source_file assert lines[1] == expected assert str(paths.work.join(source_file)) in created else: assert not paths.work.join(file_path).exists() assert str(paths.work.join(source_file)) not in created
def test_invalid_links_removed(runner, yadm_y, paths): """Links to invalid alternative files are removed This test ensures that when an already linked alternative becomes invalid due to a change in class, the alternate link is removed. """ # set the class tst_class = 'testclass' utils.set_local(paths, 'class', tst_class) # create files which match the test class utils.create_alt_files(paths, f'##{tst_class}') # run alt to trigger linking env = os.environ.copy() env['YADM_COMPATIBILITY'] = '1' run = runner(yadm_y('alt'), env=env) assert run.success assert run.err == '' linked = utils.parse_alt_output(run.out) # assert the proper linking has occurred for file_path in TEST_PATHS: source_file = file_path + '##' + tst_class assert paths.work.join(file_path).islink() target = py.path.local(os.path.realpath(paths.work.join(file_path))) if target.isfile(): assert paths.work.join(file_path).read() == source_file assert str(paths.work.join(source_file)) in linked else: assert paths.work.join(file_path).join( utils.CONTAINED).read() == source_file assert str(paths.work.join(source_file)) in linked # change the class so there are no valid alternates utils.set_local(paths, 'class', 'changedclass') # run alt to trigger linking env = os.environ.copy() env['YADM_COMPATIBILITY'] = '1' run = runner(yadm_y('alt'), env=env) assert run.success assert run.err == '' linked = utils.parse_alt_output(run.out) # assert the linking is removed for file_path in TEST_PATHS: source_file = file_path + '##' + tst_class assert not paths.work.join(file_path).exists() assert str(paths.work.join(source_file)) not in linked
def test_jinja_envtpl_missing(runner, paths): """Test operation when envtpl is missing""" script = f""" YADM_TEST=1 source {paths.pgm} process_global_args -Y "{paths.yadm}" set_operating_system configure_paths ENVTPL_PROGRAM='envtpl_missing' main alt """ utils.create_alt_files(paths, '##yadm.j2') run = runner(command=['bash'], inp=script) assert run.success assert run.err == '' assert f'envtpl not available, not creating' in run.out
def test_local_override(runner, yadm_y, paths, tst_distro, envtpl_present): """Test local overrides""" if not envtpl_present: pytest.skip('Unable to test without envtpl.') # define local overrides utils.set_local(paths, 'class', 'or-class') utils.set_local(paths, 'hostname', 'or-hostname') utils.set_local(paths, 'os', 'or-os') utils.set_local(paths, 'user', 'or-user') template = ('j2-{{ YADM_CLASS }}-' '{{ YADM_OS }}-{{ YADM_HOSTNAME }}-' '{{ YADM_USER }}-{{ YADM_DISTRO }}' '-{%- ' f"include '{utils.INCLUDE_FILE}'" ' -%}') expected = (f'j2-or-class-or-os-or-hostname-or-user-{tst_distro}' f'-{utils.INCLUDE_CONTENT}') utils.create_alt_files(paths, '##yadm.j2', content=template, includefile=True) # os.system(f'find {paths.work}' + ' -name *j2 -ls -exec cat \'{}\' ";"') # os.system(f'find {paths.work}') # run alt to trigger linking env = os.environ.copy() env['YADM_COMPATIBILITY'] = '1' run = runner(yadm_y('alt'), env=env) assert run.success assert run.err == '' created = utils.parse_alt_output(run.out, linked=False) # assert the proper creation has occurred for file_path in (utils.ALT_FILE1, utils.ALT_FILE2): source_file = file_path + '##yadm.j2' assert paths.work.join(file_path).isfile() lines = paths.work.join(file_path).readlines(cr=False) assert lines[0] == source_file assert lines[1] == expected assert str(paths.work.join(source_file)) in created
def test_alt_templates(runner, paths, kind, label): """Test templates supported by yadm alt""" yadm_dir = setup_standard_yadm_dir(paths) suffix = f'##{label}.{kind}' if kind is None: suffix = f'##{label}' utils.create_alt_files(paths, suffix) run = runner([paths.pgm, '-Y', yadm_dir, 'alt']) assert run.success assert run.err == '' created = utils.parse_alt_output(run.out, linked=False) for created_path in TEST_PATHS: if created_path != utils.ALT_DIR: source_file = created_path + suffix assert paths.work.join(created_path).isfile() assert paths.work.join(created_path).read().strip() == source_file assert str(paths.work.join(source_file)) in created
def test_wild(request, runner, yadm_y, paths, tst_sys, tst_host, tst_user, tracked, encrypt, wild_class, wild_host, wild_sys, wild_user, template): """Test wild linking These tests are done by creating permutations of the possible files using WILD_TEMPLATES. Each case is then tested (while skipping the already tested permutations for efficiency). """ if request.node.name in BROKEN_TEST_IDS: pytest.xfail( 'This test is known to be broken. ' 'This bug needs to be fixed.') tst_class = 'testclass' # determine the "wild" version of the suffix str_class = '%' if wild_class else tst_class str_host = '%' if wild_host else tst_host str_sys = '%' if wild_sys else tst_sys str_user = '******' if wild_user else tst_user wild_suffix = string.Template(template).substitute( tst_class=str_class, tst_host=str_host, tst_sys=str_sys, tst_user=str_user, ) # determine the "standard" version of the suffix std_suffix = string.Template(template).substitute( tst_class=tst_class, tst_host=tst_host, tst_sys=tst_sys, tst_user=tst_user, ) # skip over duplicate tests (this seems to be the simplest way to cover the # permutations of tests, while skipping duplicates.) test_key = f'{tracked}{encrypt}{wild_suffix}{std_suffix}' if test_key in WILD_TESTED: return WILD_TESTED.add(test_key) # set the class utils.set_local(paths, 'class', tst_class) # create files using the wild suffix utils.create_alt_files(paths, wild_suffix, tracked=tracked, encrypt=encrypt, exclude=False) # run alt to trigger linking run = runner(yadm_y('alt')) assert run.success assert run.err == '' linked = linked_list(run.out) # assert the proper linking has occurred for file_path in TEST_PATHS: source_file = file_path + wild_suffix assert paths.work.join(file_path).islink() target = py.path.local(paths.work.join(file_path).readlink()) if target.isfile(): assert paths.work.join(file_path).read() == source_file assert str(paths.work.join(source_file)) in linked else: assert paths.work.join(file_path).join( utils.CONTAINED).read() == source_file assert str(paths.work.join(source_file)) in linked # create files using the standard suffix utils.create_alt_files(paths, std_suffix, tracked=tracked, encrypt=encrypt, exclude=False) # run alt to trigger linking run = runner(yadm_y('alt')) assert run.success assert run.err == '' linked = linked_list(run.out) # assert the proper linking has occurred for file_path in TEST_PATHS: source_file = file_path + std_suffix assert paths.work.join(file_path).islink() target = py.path.local(paths.work.join(file_path).readlink()) if target.isfile(): assert paths.work.join(file_path).read() == source_file assert str(paths.work.join(source_file)) in linked else: assert paths.work.join(file_path).join( utils.CONTAINED).read() == source_file assert str(paths.work.join(source_file)) in linked