Coverage for tests / unit / no_torch / test_serializing_edge_cases.py: 100%

60 statements  

« prev     ^ index     » next       coverage.py v7.13.4, created at 2026-02-22 01:52 -0700

1"""Edge case tests for zanj/serializing.py to improve coverage.""" 

2 

3from __future__ import annotations 

4 

5import numpy as np 

6import pytest 

7 

8from zanj import ZANJ 

9from zanj.serializing import zanj_external_serialize 

10 

11 

12class TestZanjExternalSerialize: 

13 """Tests for zanj_external_serialize function edge cases.""" 

14 

15 def test_duplicate_external_path(self): 

16 """Lines 124-127: Duplicate external path should raise ValueError.""" 

17 z = ZANJ() 

18 array1 = np.random.rand(10, 10) 

19 array2 = np.random.rand(5, 5) 

20 

21 # First call with path ('data',) should succeed 

22 zanj_external_serialize( 

23 z, array1, path=("data",), item_type="npy", _format="numpy.ndarray:external" 

24 ) 

25 

26 # Second call with same path should raise ValueError 

27 with pytest.raises(ValueError, match="already exists"): 

28 zanj_external_serialize( 

29 z, 

30 array2, 

31 path=("data",), 

32 item_type="npy", 

33 _format="numpy.ndarray:external", 

34 ) 

35 

36 def test_path_prefix_conflict_child_first(self): 

37 """Lines 137-142: Path prefix conflict where new path is parent of existing.""" 

38 z = ZANJ() 

39 array1 = np.random.rand(10, 10) 

40 array2 = np.random.rand(5, 5) 

41 

42 # First: add child path 'layer/1/weight' 

43 zanj_external_serialize( 

44 z, 

45 array1, 

46 path=("layer", "1", "weight"), 

47 item_type="npy", 

48 _format="numpy.ndarray:external", 

49 ) 

50 

51 # Second: try to add parent path 'layer/1' - should conflict 

52 with pytest.raises(ValueError, match="is a prefix of another path"): 

53 zanj_external_serialize( 

54 z, 

55 array2, 

56 path=("layer", "1"), 

57 item_type="npy", 

58 _format="numpy.ndarray:external", 

59 ) 

60 

61 def test_path_prefix_conflict_parent_first(self): 

62 """Lines 134-136: Path prefix conflict where new path is child of existing.""" 

63 z = ZANJ() 

64 array1 = np.random.rand(10, 10) 

65 array2 = np.random.rand(5, 5) 

66 

67 # First: add parent path 'layer/1' 

68 zanj_external_serialize( 

69 z, 

70 array1, 

71 path=("layer", "1"), 

72 item_type="npy", 

73 _format="numpy.ndarray:external", 

74 ) 

75 

76 # Second: try to add child path 'layer/1/weight' - should conflict 

77 with pytest.raises(ValueError, match="is a prefix of another path"): 

78 zanj_external_serialize( 

79 z, 

80 array2, 

81 path=("layer", "1", "weight"), 

82 item_type="npy", 

83 _format="numpy.ndarray:external", 

84 ) 

85 

86 def test_invalid_npy_data_type(self): 

87 """Line 160: Invalid data type for NPY serialization should raise TypeError.""" 

88 z = ZANJ() 

89 

90 # Pass a string instead of array - should fail 

91 with pytest.raises(TypeError, match="expected numpy.ndarray"): 

92 zanj_external_serialize( 

93 z, 

94 data="not an array", 

95 path=("test",), 

96 item_type="npy", 

97 _format="numpy.ndarray:external", 

98 ) 

99 

100 def test_invalid_jsonl_data_type(self): 

101 """Line 184: Invalid data type for JSONL serialization should raise TypeError.""" 

102 z = ZANJ() 

103 

104 # Create a custom class that is not iterable/sequence/dataframe 

105 class NotSerializableAsJsonl: 

106 pass 

107 

108 obj = NotSerializableAsJsonl() 

109 

110 with pytest.raises(TypeError, match="expected list or pandas.DataFrame"): 

111 zanj_external_serialize( 

112 z, 

113 data=obj, 

114 path=("test",), 

115 item_type="jsonl", 

116 _format="list:external", 

117 ) 

118 

119 def test_valid_npy_serialization(self): 

120 """Verify valid NPY serialization works correctly.""" 

121 z = ZANJ() 

122 array = np.random.rand(10, 10) 

123 

124 result = zanj_external_serialize( 

125 z, 

126 array, 

127 path=("valid_array",), 

128 item_type="npy", 

129 _format="numpy.ndarray:external", 

130 ) 

131 

132 assert "__muutils_format__" in result 

133 assert result["__muutils_format__"] == "numpy.ndarray:external" 

134 assert "valid_array.npy" in z._externals 

135 

136 def test_valid_jsonl_list_serialization(self): 

137 """Verify valid JSONL list serialization works correctly.""" 

138 z = ZANJ() 

139 data = [{"a": 1}, {"b": 2}, {"c": 3}] 

140 

141 result = zanj_external_serialize( 

142 z, 

143 data, 

144 path=("valid_list",), 

145 item_type="jsonl", 

146 _format="list:external", 

147 ) 

148 

149 assert "__muutils_format__" in result 

150 assert result["__muutils_format__"] == "list:external" 

151 assert "valid_list.jsonl" in z._externals 

152 

153 def test_non_overlapping_paths_allowed(self): 

154 """Verify that non-overlapping paths with similar prefixes are allowed.""" 

155 z = ZANJ() 

156 array1 = np.random.rand(10, 10) 

157 array2 = np.random.rand(5, 5) 

158 

159 # These should NOT conflict: 'layer.1' and 'layer.1.weight' as strings 

160 # but 'layer/1' and 'layer/10' should be fine 

161 zanj_external_serialize( 

162 z, 

163 array1, 

164 path=("layer", "1"), 

165 item_type="npy", 

166 _format="numpy.ndarray:external", 

167 ) 

168 

169 # 'layer/10' is NOT a prefix of 'layer/1' or vice versa 

170 zanj_external_serialize( 

171 z, 

172 array2, 

173 path=("layer", "10"), 

174 item_type="npy", 

175 _format="numpy.ndarray:external", 

176 ) 

177 

178 assert "layer/1.npy" in z._externals 

179 assert "layer/10.npy" in z._externals