@@ -59,11 +59,15 @@ TESTS_LIB = os.path.join(ROOT, 'tests', 'lib', 'jibb.hoon')
60# Desks the repo builds, and the folders each is assembled from, in
60# Desks the repo builds, and the folders each is assembled from, in
61# order. Every desk gets every package under vendor/. A folder is
61# order. Every desk gets every package under vendor/. A folder is
62−# (repo folder, desk folder, folders left out).
62+# (repo folder, desk folder, folders and files left out). The test
63+# desk holds my-app's sources under /my-app, so tests read them there
64+# instead of keeping copies.
64 'my-app': [('jibb-dev', '', ['tests']), ('my-app', '', [])],
66 'my-app': [('jibb-dev', '', ['tests']), ('my-app', '', [])],
65 'jibb': [('jibb', '', [])],
67 'jibb': [('jibb', '', [])],
66− 'jibb-dev': [('jibb-dev', '', []), ('tests', 'tests', [])],
68+ 'jibb-dev': [('jibb-dev', '', []), ('tests', 'tests', []),
70+ ['desk.bill', 'desk.docket-0', 'sys.kelvin'])],
68# The test desk has no sys.kelvin of its own; Clay refuses a commit
72# The test desk has no sys.kelvin of its own; Clay refuses a commit
69# without one, so it gets the %jibb desk's.
73# without one, so it gets the %jibb desk's.
@@ -861,7 +865,7 @@ class Assembly:
861 if fn.startswith('.'):
865 if fn.startswith('.'):
863 rel = os.path.join(rel_dir, fn)
867 rel = os.path.join(rel_dir, fn)
864− if drop and drop(rel):
868+ if rel in skip or (drop and drop(rel)):
866 desk_rel = os.path.join(into, rel) if into else rel
870 desk_rel = os.path.join(into, rel) if into else rel
867 with open(os.path.join(dirpath, fn), 'rb') as f:
871 with open(os.path.join(dirpath, fn), 'rb') as f:
@@ -903,7 +907,11 @@ def assemble(desk, lib=None, golden=None):
903 (isolated and rel.startswith('lib' + os.sep) and
907 (isolated and rel.startswith('lib' + os.sep) and
904 rel.endswith('.hoon')))
908 rel.endswith('.hoon')))
905 if os.path.isdir(golden):
909 if os.path.isdir(golden):
910+ # A case file that links to a file the desk already
911+ # holds, such as one of my-app's, is read from there.
906− a.add_tree(golden, os.path.join('tests', 'golden'))
912+ a.add_tree(golden, os.path.join('tests', 'golden'),
913+ drop=lambda rel: linked_desk_path(
914+ desk, os.path.join(golden, rel)) is not None)
907 a.add(os.path.join('tests', 'lib', 'jibb.hoon'),
915 a.add(os.path.join('tests', 'lib', 'jibb.hoon'),
908 generate_tests(golden).encode(),
916 generate_tests(golden).encode(),
909 'tools/ship gen-tests --golden %s' % show(golden))
917 'tools/ship gen-tests --golden %s' % show(golden))
@@ -921,6 +929,30 @@ def assemble(desk, lib=None, golden=None):
932+def linked_desk_path(desk, path):
933+ """The desk path of the file a symlink names, when the desk holds
934+ that file through another of its folders, or None."""
935+ if not os.path.islink(path):
937+ real = os.path.realpath(path)
938+ for folder, into, skip in DESKS[desk]:
939+ if folder == 'tests':
941+ rel = os.path.relpath(real, os.path.realpath(os.path.join(ROOT, folder)))
942+ if rel.startswith('..') or any(rel == s or rel.startswith(s + os.sep)
945+ return os.path.join(into, rel) if into else rel
949+def clay_file(desk, path, default):
950+ """How a generated /* names a golden case file: by the desk path
951+ of the file it links to, as linked_desk_path finds it, or default."""
952+ rel = linked_desk_path(desk, path)
953+ return '/' + '/'.join(clay_path(rel)) if rel is not None else default
924def check_assembly(a):
956def check_assembly(a):
925 problems = []
957 problems = []
926 for rel in sorted(a.files):
958 for rel in sorted(a.files):
@@ -956,6 +988,7 @@ TESTS_HEADER = """\
956:: Each file holds the output plus one newline. An expect-types: line
988:: Each file holds the output plus one newline. An expect-types: line
957:: or types.txt opts a case into golden-types and its types.txt output.
989:: or types.txt opts a case into golden-types and its types.txt output.
958:: Files come in through /*; a missing expected output fails its case.
990:: Files come in through /*; a missing expected output fails its case.
991+:: A case file that links to one of my-app's is read from /my-app.
959:: tools/ship test syncs the desk and runs -test /=jibb-dev=/tests.
992:: tools/ship test syncs the desk and runs -test /=jibb-dev=/tests.
961:: The .txt files reach Clay through the %txt mark, as lines, so the
994:: The .txt files reach Clay through the %txt mark, as lines, so the
@@ -1093,7 +1126,9 @@ def generate_tests(golden):
1093 for i, ((name, folder), arm) in enumerate(
1126 for i, ((name, folder), arm) in enumerate(
1094 zip(cases, arm_names([c[0] for c in cases])), 1):
1127 zip(cases, arm_names([c[0] for c in cases])), 1):
1095 base = '/tests/golden/%s' % name
1128 base = '/tests/golden/%s' % name
1096− lines.append('/* src-%d %%jibb %s/source/jibb' % (i, base))
1129+ lines.append('/* src-%d %%jibb %s' % (i, clay_file(
1130+ 'jibb-dev', os.path.join(folder, 'source.jibb'),
1131+ '%s/source/jibb' % base)))
1097 # a knot literal: a case's name may hold . and _, which a
1132 # a knot literal: a case's name may hold . and _, which a
1098 # path literal in Hoon can't, though /* takes them
1133 # path literal in Hoon can't, though /* takes them
@@ -1117,10 +1152,10 @@ def generate_tests(golden):
1117 args.append('~')
1152 args.append('~')
1118 call = '(%s %s)' % ('check-at' if logical else 'check', ' '.join(args))
1153 call = '(%s %s)' % ('check-at' if logical else 'check', ' '.join(args))
1119 module_fixtures = []
1154 module_fixtures = []
1120− for j, (module, at, _) in enumerate(modules, 1):
1155+ for j, (module, at, fixture) in enumerate(modules, 1):
1121 face = 'mod-%d-%d' % (i, j)
1156 face = 'mod-%d-%d' % (i, j)
1122− lines.append('/* %s %%jibb %s/modules%s/jibb' %
1157+ lines.append('/* %s %%jibb %s' % (face, clay_file(
1123− (face, base, module[:-5]))
1158+ 'jibb-dev', fixture, '%s/modules%s/jibb' % (base, module[:-5]))))
1124 module_fixtures.append('[%s %s %s]' % (hoon_cord(module.encode()), at, face))
1159 module_fixtures.append('[%s %s %s]' % (hoon_cord(module.encode()), at, face))
1125 if golden_case.wants_types(folder):
1160 if golden_case.wants_types(folder):
1126 if os.path.isfile(os.path.join(folder, 'types.txt')):
1161 if os.path.isfile(os.path.join(folder, 'types.txt')):
@@ -2286,9 +2321,10 @@ EPILOG = """\
2287 my-app vendor/* + jibb-dev (without any tests/) + my-app
2322 my-app vendor/* + jibb-dev (without any tests/) + my-app
2288 jibb vendor/* + jibb
2323 jibb vendor/* + jibb
2324+ jibb-dev vendor/* + jibb-dev + tests + my-app (under /my-app, without
2289− jibb-dev vendor/* + jibb-dev + tests, the test desk: tests/golden from
2325+ its desk files), the test desk: tests/golden from --golden,
2326+ less the case files that link to my-app, tests/lib/jibb.hoon
2290− --golden, tests/lib/jibb.hoon generated from it, and sys.kelvin
2327+ generated from it, and sys.kelvin from jibb/
2292A sync creates the desk if it's missing (as |new-desk does), mounts it at
2328A sync creates the desk if it's missing (as |new-desk does), mounts it at
2293<pier>/<desk>, makes the mount hold exactly the desk's files, runs
2329<pier>/<desk>, makes the mount hold exactly the desk's files, runs
2294|commit, and waits until the desk matches the repo, checking every file.
2330|commit, and waits until the desk matches the repo, checking every file.