1
+ <?php
2
+
3
+ namespace tool_objectfs \local ;
4
+
5
+ use coding_exception ;
6
+ use tool_objectfs \local \manager ;
7
+ use tool_objectfs \local \tag \tag_manager ;
8
+ use tool_objectfs \local \tag \tag_source ;
9
+ use tool_objectfs \tests \testcase ;
10
+
11
+ class tagging_test extends testcase {
12
+ public function test_get_defined_tag_sources () {
13
+ $ sources = tag_manager::get_defined_tag_sources ();
14
+ $ this ->assertIsArray ($ sources );
15
+
16
+ // Both AWS and Azure limit 10 tags per object, so ensure never more than 10 sources defined.
17
+ $ this ->assertLessThanOrEqual (10 , count ($ sources ));
18
+ }
19
+
20
+ public static function tag_source_provider (): array {
21
+ $ sources = tag_manager::get_defined_tag_sources ();
22
+ $ tests = [];
23
+
24
+ foreach ($ sources as $ source ) {
25
+ $ tests [$ source ->get_identifier ()] = [
26
+ 'source ' => $ source
27
+ ];
28
+ }
29
+
30
+ return $ tests ;
31
+ }
32
+
33
+ /**
34
+ * @dataProvider tag_source_provider
35
+ */
36
+ public function test_tag_sources_identifier (tag_source $ source ) {
37
+ // Ensure tag source is < 128 chars, to fit AWS & Azure spec.
38
+ $ count = strlen ($ source ->get_identifier ());
39
+ $ this ->assertLessThan (128 , $ count );
40
+ $ this ->assertGreaterThan (0 , $ count );
41
+ }
42
+
43
+ public static function is_tagging_enabled_provider (): array {
44
+ return [
45
+ 'neither config nor fs supports ' => [
46
+ 'enabledinconfig ' => false ,
47
+ 'supportedbyfs ' => false ,
48
+ 'expected ' => false ,
49
+ ],
50
+ 'enabled in config but fs does not support ' => [
51
+ 'enabledinconfig ' => true ,
52
+ 'supportedbyfs ' => false ,
53
+ 'expected ' => false ,
54
+ ],
55
+ 'enabled in config and fs does support ' => [
56
+ 'enabledinconfig ' => true ,
57
+ 'supportedbyfs ' => true ,
58
+ 'expected ' => true ,
59
+ ],
60
+ ];
61
+ }
62
+
63
+ /**
64
+ * @dataProvider is_tagging_enabled_provider
65
+ */
66
+ public function test_is_tagging_enabled (bool $ enabledinconfig , bool $ supportedbyfs , bool $ expected ) {
67
+ global $ CFG ;
68
+ // Set config.
69
+ set_config ('taggingenabled ' , $ enabledinconfig , 'tool_objectfs ' );
70
+
71
+ // Set supported by fs.
72
+ $ config = manager::get_objectfs_config ();
73
+ $ config ->taggingenabled = $ enabledinconfig ;
74
+ $ config ->enabletasks = true ;
75
+ $ config ->filesystem = '\\tool_objectfs \\tests \\test_file_system ' ;
76
+ manager::set_objectfs_config ($ config );
77
+ $ CFG ->phpunit_objectfs_supports_object_tagging = $ supportedbyfs ;
78
+
79
+ $ this ->assertEquals ($ expected , tag_manager::is_tagging_enabled ());
80
+ }
81
+
82
+ public function test_query_local_tags () {
83
+ global $ DB ;
84
+
85
+ // Setup some fake tag data.
86
+ $ DB ->insert_records ('tool_objectfs_object_tags ' , [
87
+ [
88
+ 'contenthash ' => 'abc123 ' ,
89
+ 'tagkey ' => 'test ' ,
90
+ 'tagvalue ' => 'test ' ,
91
+ 'timemodified ' => time ()
92
+ ],
93
+ [
94
+ 'contenthash ' => 'abc123 ' ,
95
+ 'tagkey ' => 'test2 ' ,
96
+ 'tagvalue ' => 'test2 ' ,
97
+ 'timemodified ' => time ()
98
+ ]
99
+ ]);
100
+
101
+ $ this ->assertCount (2 , tag_manager::query_local_tags ('abc123 ' ));
102
+ $ this ->assertCount (0 , tag_manager::query_local_tags ('doesnotexist ' ));
103
+ }
104
+
105
+ public function test_update_tags_if_necessary () {
106
+ global $ DB ;
107
+
108
+ // There should be no existing tags to begin with.
109
+ $ this ->assertEmpty (tag_manager::query_local_tags ('test ' ));
110
+
111
+ // Update tags if necessary - should update the tags.
112
+ tag_manager::update_tags_if_necessary ('test ' );
113
+
114
+ // Query tags - should be equal to number defined by the manager.
115
+ $ expectedcount = count (tag_manager::get_defined_tag_sources ());
116
+ $ this ->assertCount ($ expectedcount , tag_manager::query_local_tags ('test ' ), 'Tags created match the number defined by manager ' );
117
+
118
+ // Note the timemodified of one of the tags.
119
+ $ timemodified = $ DB ->get_field ('tool_objectfs_object_tags ' , 'timemodified ' , ['contenthash ' => 'test ' , 'tagkey ' => tag_manager::get_defined_tag_sources ()[0 ]->get_identifier ()]);
120
+
121
+ // Running again, timemodified should not change.
122
+ $ this ->waitForSecond ();
123
+ tag_manager::update_tags_if_necessary ('test ' );
124
+
125
+ $ newtimemodified = $ DB ->get_field ('tool_objectfs_object_tags ' , 'timemodified ' , ['contenthash ' => 'test ' , 'tagkey ' => tag_manager::get_defined_tag_sources ()[0 ]->get_identifier ()]);
126
+ $ this ->assertEquals ($ timemodified , $ newtimemodified , 'Tags timemodified must not change if not forced and values are not different ' );
127
+
128
+ // Except if it is forced.
129
+ $ this ->waitForSecond ();
130
+ tag_manager::update_tags_if_necessary ('test ' , true );
131
+
132
+ $ timemodifiedafterforce = $ DB ->get_field ('tool_objectfs_object_tags ' , 'timemodified ' , ['contenthash ' => 'test ' , 'tagkey ' => tag_manager::get_defined_tag_sources ()[0 ]->get_identifier ()]);
133
+ $ this ->assertNotEquals ($ timemodified , $ timemodifiedafterforce , 'Forced tag update changed time modified ' );
134
+ }
135
+
136
+ public static function get_objects_needing_sync_provider (): array {
137
+ return [
138
+ 'duplicated, needs sync ' => [
139
+ 'location ' => OBJECT_LOCATION_DUPLICATED ,
140
+ 'status ' => tag_manager::SYNC_STATUS_NEEDS_SYNC ,
141
+ 'expectedneedssync ' => true ,
142
+ ],
143
+ 'remote, needs sync ' => [
144
+ 'location ' => OBJECT_LOCATION_EXTERNAL ,
145
+ 'status ' => tag_manager::SYNC_STATUS_NEEDS_SYNC ,
146
+ 'expectedneedssync ' => true ,
147
+ ],
148
+ 'local, needs sync ' => [
149
+ 'location ' => OBJECT_LOCATION_LOCAL ,
150
+ 'status ' => tag_manager::SYNC_STATUS_NEEDS_SYNC ,
151
+ 'expectedneedssync ' => false ,
152
+ ],
153
+ 'duplicated, does not need sync ' => [
154
+ 'location ' => OBJECT_LOCATION_DUPLICATED ,
155
+ 'status ' => tag_manager::SYNC_STATUS_SYNC_NOT_REQUIRED ,
156
+ 'expectedneedssync ' => false ,
157
+ ],
158
+ 'local, does not need sync ' => [
159
+ 'location ' => OBJECT_LOCATION_LOCAL ,
160
+ 'status ' => tag_manager::SYNC_STATUS_SYNC_NOT_REQUIRED ,
161
+ 'expectedneedssync ' => false ,
162
+ ],
163
+ ];
164
+ }
165
+
166
+ /**
167
+ * @dataProvider get_objects_needing_sync_provider
168
+ */
169
+ public function test_get_objects_needing_sync (int $ location , int $ syncstatus , bool $ expectedneedssync ) {
170
+ global $ DB ;
171
+
172
+ // Create the test object at the required location.
173
+ switch ($ location ) {
174
+ case OBJECT_LOCATION_DUPLICATED :
175
+ $ object = $ this ->create_duplicated_object ();
176
+ break ;
177
+ case OBJECT_LOCATION_LOCAL :
178
+ $ object = $ this ->create_local_object ();
179
+ break ;
180
+ case OBJECT_LOCATION_EXTERNAL :
181
+ $ object = $ this ->create_remote_object ();
182
+ break ;
183
+ default :
184
+ throw new coding_exception ("Object location not handled in test " );
185
+ }
186
+
187
+ // Set the sync status.
188
+ $ DB ->set_field ('tool_objectfs_objects ' , 'tagsyncstatus ' , $ syncstatus , ['id ' => $ object ->id ]);
189
+
190
+ // Check if it is included in the list.
191
+ $ needssync = tag_manager::get_objects_needing_sync (1 );
192
+
193
+ if ($ expectedneedssync ) {
194
+ $ this ->assertContains ($ object ->contenthash , $ needssync );
195
+ } else {
196
+ $ this ->assertNotContains ($ object ->contenthash , $ needssync );
197
+ }
198
+ }
199
+
200
+ public function test_get_objects_needing_sync_limit () {
201
+ global $ DB ;
202
+
203
+ // Create two duplicated objects needing sync.
204
+ $ object = $ this ->create_duplicated_object ();
205
+ $ DB ->set_field ('tool_objectfs_objects ' , 'tagsyncstatus ' , tag_manager::SYNC_STATUS_NEEDS_SYNC , ['id ' => $ object ->id ]);
206
+ $ object = $ this ->create_remote_object ();
207
+ $ DB ->set_field ('tool_objectfs_objects ' , 'tagsyncstatus ' , tag_manager::SYNC_STATUS_NEEDS_SYNC , ['id ' => $ object ->id ]);
208
+
209
+ // Ensure a limit of 2 returns 2, and limit of 1 returns 1.
210
+ $ this ->assertCount (2 , tag_manager::get_objects_needing_sync (2 ));
211
+ $ this ->assertCount (1 , tag_manager::get_objects_needing_sync (1 ));
212
+ }
213
+ }
0 commit comments