P08-03: 配置の通常操作受入
This commit is contained in:
+26
@@ -241,6 +241,24 @@ def make(base, source, checker):
|
||||
formal = folder/'formal'
|
||||
formal.mkdir()
|
||||
for member in checker.MEMBERS: (formal/member).write_text('synthetic '+member+'\n')
|
||||
shutil.copytree(formal, folder/'formal.bak')
|
||||
shutil.copyfile(formal/'manifest.json', folder/'formal-slot-metadata.json')
|
||||
profile = '/synthetic-private-profile'
|
||||
absolute = profile+'/saves/manual_ui'
|
||||
put(folder/'formal-export.json', {'pid':pids[0], 'requested_path':'user://saves/manual_ui',
|
||||
'absolute_path':absolute, 'user_data_dir':profile,
|
||||
'packages':{name:{'present':True, 'source_path':absolute+suffix,
|
||||
'members':{n:{'sha256':sha(folder/name/n),'bytes':(folder/name/n).stat().st_size} for n in checker.MEMBERS}}
|
||||
for name,suffix in [('formal',''),('formal.bak','.bak')]},
|
||||
'slot_metadata':{'file':'formal-slot-metadata.json','sha256':sha(formal/'manifest.json')}})
|
||||
for role,pid,op in [('writer',pids[0],'save'),('reader',pids[1],'load')]:
|
||||
stem = role+'-save-result-0001'
|
||||
(folder/(stem+'.var')).write_bytes(b'synthetic raw Dictionary stand-in')
|
||||
put(folder/(stem+'.json'), {'pid':pid,'operation':'runtime_operation',
|
||||
'requested_path':'user://saves/manual_ui','absolute_path':absolute,'user_data_dir':profile,
|
||||
'result':typed({'ok':True,'operation':op,'save_path':'user://saves/manual_ui'}),
|
||||
'raw_sha256':sha(folder/(stem+'.var'))})
|
||||
put(folder/(role+'-save-results.json'), {'pid':pid,'records':[stem]})
|
||||
put(folder/'save.json', {'members': {n: sha(formal/n) for n in checker.MEMBERS},
|
||||
'pid': pids[0], 'cell': target, 'instance_id': 'f4'})
|
||||
row = {'id': 'resume_overlap', 'kind': 'build', 'position': position(target),
|
||||
@@ -259,6 +277,14 @@ def make(base, source, checker):
|
||||
pair('pair', [101, 102], 'handler')
|
||||
pair('os-pair', [201, 202], 'native_os')
|
||||
shutil.copytree(out/'pair/formal', out/'pair/initial-formal')
|
||||
initial = copy.deepcopy(json.loads((out/'pair/formal-export.json').read_text()))
|
||||
initial.update(requested_path='user://saves/p08_initial',absolute_path='/synthetic-private-profile/saves/p08_initial')
|
||||
initial['packages'] = {'initial-formal':initial['packages']['formal'],
|
||||
'initial-formal.bak':{'present':False,'source_path':initial['absolute_path']+'.bak','members':{}}}
|
||||
initial['packages']['initial-formal']['source_path'] = initial['absolute_path']
|
||||
shutil.copyfile(out/'pair/initial-formal/manifest.json',out/'pair/initial-formal-slot-metadata.json')
|
||||
initial['slot_metadata']['file'] = 'initial-formal-slot-metadata.json'
|
||||
put(out/'pair/initial-formal-export.json',initial)
|
||||
for role, pid in (('writer',201),('reader',202)):
|
||||
prefix = 'os-runs/'+role+'/'
|
||||
folder = out/prefix
|
||||
|
||||
+2
-6
@@ -73,6 +73,7 @@ func setup() -> void:
|
||||
if role == "writer":
|
||||
await load_menu(main.find_child("SaveLoadMenu", true, false))
|
||||
var stored: Dictionary = SaveService.inspect_snapshot(ProjectSettings.globalize_path(String(main.manual_save_path)))
|
||||
record_save_result("initial_inspect", String(main.manual_save_path), stored)
|
||||
expect(bool(stored.get("ok", false)), "read-only initial formal inspection")
|
||||
expect(runtime.create_snapshot() == stored.get("snapshot", {}), "OS initial formal model exact")
|
||||
expect(clock.paused, "diagnostic formal fixture starts paused")
|
||||
@@ -154,12 +155,7 @@ func load_menu(menu: MenuButton) -> void:
|
||||
await request(action)
|
||||
|
||||
func archive_formal() -> void:
|
||||
DirAccess.make_dir_recursive_absolute(directory.path_join("formal"))
|
||||
for member: String in MEMBERS:
|
||||
var source := ProjectSettings.globalize_path(String(main.manual_save_path)).path_join(member)
|
||||
var destination := directory.path_join("formal/" + member)
|
||||
expect(DirAccess.copy_absolute(source, destination) == OK, "archive formal " + member)
|
||||
expect(FileAccess.get_sha256(source) == FileAccess.get_sha256(destination), "archive formal SHA " + member)
|
||||
export_package(String(main.manual_save_path), "formal")
|
||||
|
||||
func finish_observations() -> void:
|
||||
json_file(role + "-requests.json", {"pid": OS.get_process_id(), "requests": all_requests})
|
||||
|
||||
Vendored
+74
-4
@@ -18,6 +18,9 @@ var target := Vector3i(-8, 0, 0)
|
||||
var budget: Dictionary = {}
|
||||
var input_method := "handler"
|
||||
var observed_cell: Variant = null
|
||||
var save_serial := 0
|
||||
var save_records: Array = []
|
||||
const INITIAL_SAVE := "user://saves/p08_initial"
|
||||
|
||||
func annotate(row: Dictionary) -> void:
|
||||
row["input_method"] = input_method
|
||||
@@ -69,6 +72,8 @@ func button(node: BaseButton) -> void:
|
||||
expect(node != null and not node.disabled, "available production button")
|
||||
if node == null or node.disabled:
|
||||
return
|
||||
if node.toggle_mode:
|
||||
node.button_pressed = not node.button_pressed
|
||||
node.pressed.emit()
|
||||
await frames()
|
||||
|
||||
@@ -77,7 +82,9 @@ func choose(id: StringName) -> void:
|
||||
await button(main.palette_toggle_button)
|
||||
var node: Button = main.build_buttons[id]
|
||||
await reveal(node)
|
||||
await button(node)
|
||||
if not node.button_pressed:
|
||||
await button(node)
|
||||
expect(node.button_pressed and main._selected_definition_id == id, "chosen production definition")
|
||||
|
||||
func click(cell: Vector3i) -> Dictionary:
|
||||
var view: WorldPreview = main.world_preview
|
||||
@@ -253,6 +260,7 @@ func run(p_tree: SceneTree, output: String, requested_role: String) -> Dictionar
|
||||
expect(DirAccess.make_dir_recursive_absolute(directory) == OK, "diagnostic directory")
|
||||
runtime = tree.root.get_node("SimulationRuntime")
|
||||
clock = tree.root.get_node("GameClock")
|
||||
runtime.save_operation_completed.connect(record_save_operation)
|
||||
await setup()
|
||||
runtime.command_completed.connect(observe)
|
||||
main.world_preview.cell_clicked.connect(selected_cell)
|
||||
@@ -265,10 +273,12 @@ func run(p_tree: SceneTree, output: String, requested_role: String) -> Dictionar
|
||||
if requested_role == "standalone":
|
||||
role = "reader"
|
||||
actions = []
|
||||
save_records = []
|
||||
await reader(false)
|
||||
json_file(role + "-actions.json", {"setup": "diagnostic", "input_method": input_method, "actions": actions})
|
||||
finish_observations()
|
||||
runtime.command_completed.disconnect(observe)
|
||||
runtime.save_operation_completed.disconnect(record_save_operation)
|
||||
var cleanup: Dictionary = await Cleanup.free_owner_and_wait(tree, main)
|
||||
expect(cleanup.get(&"passed", false), "ordinary Main/audio cleanup")
|
||||
json_file(role + "-process.json", {"pid": OS.get_process_id(), "engine": Engine.get_version_info(), "checks": checks, "failures": failures, "role": requested_role, "setup": "diagnostic"})
|
||||
@@ -296,18 +306,78 @@ func setup() -> void:
|
||||
clock.set_paused(true)
|
||||
tree.root.size = Vector2i(1440, 810)
|
||||
main = load("res://scenes/main/main.tscn").instantiate()
|
||||
main.manual_save_path = directory.path_join("formal")
|
||||
main.manual_save_path = "user://saves/manual_ui"
|
||||
if role == "reader":
|
||||
import_package(directory.path_join("formal"), String(main.manual_save_path))
|
||||
tree.root.add_child(main)
|
||||
runtime.configure_save_policy({&"enabled": false, &"daily_checkpoint_enabled": false})
|
||||
|
||||
func save_initial_fixture() -> void:
|
||||
# Explicit diagnostic input, not an OS action or natural-play save.
|
||||
var saved: Dictionary = SaveService.save_snapshot(directory.path_join("initial-formal"), runtime.create_snapshot())
|
||||
var saved: Dictionary = SaveService.save_snapshot(INITIAL_SAVE, runtime.create_snapshot())
|
||||
record_save_result("initial_save", INITIAL_SAVE, saved)
|
||||
expect(bool(saved.get("ok", false)), "diagnostic initial formal save")
|
||||
export_package(INITIAL_SAVE, "initial-formal")
|
||||
# Seed the private normal slot, so its later normal save produces a backup.
|
||||
import_package(ProjectSettings.globalize_path(INITIAL_SAVE), String(main.manual_save_path))
|
||||
json_file("diagnostic-budget.json", budget)
|
||||
|
||||
func archive_formal() -> void:
|
||||
pass
|
||||
export_package(String(main.manual_save_path), "formal")
|
||||
|
||||
func record_save_operation(result: Dictionary) -> void:
|
||||
record_save_result("runtime_operation", String(main.manual_save_path), result)
|
||||
|
||||
func record_save_result(operation: String, path: String, result: Dictionary) -> void:
|
||||
save_serial += 1
|
||||
var stem := "%s-save-result-%04d" % [role, save_serial]
|
||||
var raw := FileAccess.open(directory.path_join(stem + ".var"), FileAccess.WRITE)
|
||||
expect(raw != null, "raw save result")
|
||||
if raw != null:
|
||||
raw.store_buffer(var_to_bytes(result))
|
||||
raw.close()
|
||||
json_file(stem + ".json", {"pid": OS.get_process_id(), "operation": operation,
|
||||
"requested_path": path, "absolute_path": ProjectSettings.globalize_path(path),
|
||||
"user_data_dir": OS.get_user_data_dir(), "result": Codec.new().typed(result),
|
||||
"raw_sha256": FileAccess.get_sha256(directory.path_join(stem + ".var"))})
|
||||
save_records.append(stem)
|
||||
json_file(role + "-save-results.json", {"pid": OS.get_process_id(), "records": save_records})
|
||||
|
||||
func import_package(source: String, destination: String) -> void:
|
||||
var absolute := ProjectSettings.globalize_path(destination)
|
||||
expect(DirAccess.make_dir_recursive_absolute(absolute) == OK, "private save directory")
|
||||
for member: String in MEMBERS:
|
||||
var origin := source.path_join(member)
|
||||
var copy := absolute.path_join(member)
|
||||
expect(DirAccess.copy_absolute(origin, copy) == OK, "private save input " + member)
|
||||
expect(FileAccess.get_sha256(origin) == FileAccess.get_sha256(copy), "private save input SHA " + member)
|
||||
|
||||
func export_package(path: String, name: String) -> void:
|
||||
var absolute := ProjectSettings.globalize_path(path)
|
||||
var pins := {}
|
||||
for suffix: String in ["", ".bak"]:
|
||||
var source := absolute + suffix
|
||||
var present := DirAccess.dir_exists_absolute(source)
|
||||
pins[name + suffix] = {"source_path": source, "present": present, "members": {}}
|
||||
if not present:
|
||||
expect(not suffix.is_empty(), "formal package exists")
|
||||
continue
|
||||
var destination := directory.path_join(name + suffix)
|
||||
expect(DirAccess.make_dir_recursive_absolute(destination) == OK, "export directory")
|
||||
for member: String in MEMBERS:
|
||||
var origin := source.path_join(member)
|
||||
var copy := destination.path_join(member)
|
||||
expect(DirAccess.copy_absolute(origin, copy) == OK, "export " + member)
|
||||
var digest := FileAccess.get_sha256(origin)
|
||||
expect(not digest.is_empty() and digest == FileAccess.get_sha256(copy), "export SHA " + member)
|
||||
pins[name + suffix]["members"][member] = {"sha256": digest, "bytes": FileAccess.get_file_as_bytes(copy).size()}
|
||||
# Slot metadata lives in the existing manifest; copy it verbatim.
|
||||
var metadata := absolute.path_join("manifest.json")
|
||||
var metadata_copy := directory.path_join(name + "-slot-metadata.json")
|
||||
expect(DirAccess.copy_absolute(metadata, metadata_copy) == OK, "slot metadata export")
|
||||
json_file(name + "-export.json", {"pid": OS.get_process_id(), "requested_path": path,
|
||||
"absolute_path": absolute, "user_data_dir": OS.get_user_data_dir(), "packages": pins,
|
||||
"slot_metadata": {"file": name + "-slot-metadata.json", "sha256": FileAccess.get_sha256(metadata_copy)}})
|
||||
|
||||
func finish_observations() -> void:
|
||||
pass
|
||||
|
||||
Reference in New Issue
Block a user