diff --git a/_test/test_unique_objects_container/store2020_1.mat b/_test/test_unique_objects_container/store2020_1.mat new file mode 100644 index 0000000000..c282e41ab8 Binary files /dev/null and b/_test/test_unique_objects_container/store2020_1.mat differ diff --git a/_test/test_unique_objects_container/store2024_1.mat b/_test/test_unique_objects_container/store2024_1.mat new file mode 100644 index 0000000000..a69bf10d68 Binary files /dev/null and b/_test/test_unique_objects_container/store2024_1.mat differ diff --git a/_test/test_unique_objects_container/store_current.mat b/_test/test_unique_objects_container/store_current.mat new file mode 100644 index 0000000000..8a8bf2ed84 Binary files /dev/null and b/_test/test_unique_objects_container/store_current.mat differ diff --git a/_test/test_unique_objects_container/test_unique_objects.m b/_test/test_unique_objects_container/test_unique_objects.m index 279f1ca989..eaef3ab98b 100644 --- a/_test/test_unique_objects_container/test_unique_objects.m +++ b/_test/test_unique_objects_container/test_unique_objects.m @@ -496,5 +496,23 @@ function test_arrays_of_containers(obj) assertTrue(isa(arr{2},'unique_objects_container')); end + function test_hashing_preserved_over_save_and_load(obj) + uoc = unique_objects_container('baseclass','IX_inst'); + uoc{1} = obj.mi1; + uoc{2} = IX_null_inst(); + % store the current uoc and compare its save/load with the + % initial construct + save('store_current.mat','uoc'); + zzz = load('store_current.mat'); + assertEqual(uoc.stored_hashes, zzz.uoc.stored_hashes); + % load the one created with R2020b and compare + zzz = load('store2020_1.mat'); + assertEqual(uoc.stored_hashes, zzz.uoc.stored_hashes); + % load the one created with r2024b and compare + zzz = load('store2024_1.mat'); + assertEqual(uoc.stored_hashes, zzz.uoc.stored_hashes); + + end + end end diff --git a/herbert_core/utilities/classes/@unique_objects_container/private/check_combo_arg_.m b/herbert_core/utilities/classes/@unique_objects_container/private/check_combo_arg_.m index 0420901a61..890704ff25 100644 --- a/herbert_core/utilities/classes/@unique_objects_container/private/check_combo_arg_.m +++ b/herbert_core/utilities/classes/@unique_objects_container/private/check_combo_arg_.m @@ -45,6 +45,10 @@ obj.baseclass,disp2str(non_type_ind),class(invalid_obj)) end end -if do_rehashify +% not doing rehashify here as hashes are now loaded from a saved object +%if do_rehashify +% obj = obj.rehashify_all(with_checks); +%end +if isempty(obj.stored_hashes_) && ~isempty(obj.unique_objects) obj = obj.rehashify_all(with_checks); end diff --git a/herbert_core/utilities/classes/@unique_objects_container/unique_objects_container.m b/herbert_core/utilities/classes/@unique_objects_container/unique_objects_container.m index b3e6299988..463b7a65f3 100644 --- a/herbert_core/utilities/classes/@unique_objects_container/unique_objects_container.m +++ b/herbert_core/utilities/classes/@unique_objects_container/unique_objects_container.m @@ -195,6 +195,20 @@ error('HERBERT:unique_objects_container:invalid_set', ... 'attempt to set unique objects in container outside of loadobj'); end + %{ + % test that the current hashing reproduces the hashing loaded + % from file. Note that this code will cause some tests to fail + % that deliberately corrupt the container. + if ~isempty(self.stored_hashes_) + for ii = 1:numel(self.stored_hashes_) + hash = self.stored_hashes_{ii}; + hash2 = Hashing.hashify_obj(self.unique_objects_{ii}); + if hash ~= hash2 + error("bad hash"); + end + end + end + %} end % function x = get.stored_hashes(self) @@ -202,6 +216,34 @@ % objects. Only really useful for debugging. x = self.stored_hashes_; end + + function self = set.stored_hashes(self, val) + %GET.STORED_HASHES - list the hashes corresponding to the unique + % objects. Only really useful for debugging. + if ~self.do_check_combo_arg_ + if ~iscell(val) + val = {val}; + end + self.stored_hashes_ = val; + else + error('HERBERT:unique_objects_container:invalid_set', ... + 'attempt to set stored hashes in container outside of loadobj'); + end + %{ + % test that the current hashing reproduces the hashing loaded + % from file. Note that this code will cause some tests to fail + % that deliberately corrupt the container. + if ~isempty(self.unique_objects_) + for ii = 1:numel(self.unique_objects) + obj = self.unique_objects_{ii}; + hash = Hashing.hashify_obj(obj); + if hash ~= self.stored_hashes_{ii} + error("bad hash"); + end + end + end + %} + end % function x = get.idx(self) %GET.IDX - get the indices of each stored object in the container @@ -795,6 +837,7 @@ function list(self,field) fields_to_save_ = { 'baseclass', ... 'unique_objects',... + 'stored_hashes', ... 'idx', ... 'conv_func_string'}; end @@ -847,9 +890,11 @@ function list(self,field) % save-able class obj = unique_objects_container(); obj = loadobj@serializable(S,obj); - if obj.do_check_combo_arg - obj.check_combo_arg(true,true); - end + % not doing a check combo arg here as it is done in the loadobj + % of serializable above + %if obj.do_check_combo_arg + % obj.check_combo_arg(true,true); + %end end function out = concatenate(objs, type)