• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2016 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.documentsui.files;
18 
19 import static junit.framework.Assert.assertEquals;
20 import static org.junit.Assert.assertTrue;
21 
22 import android.net.Uri;
23 import android.provider.DocumentsContract.Document;
24 import android.provider.DocumentsContract.Root;
25 import android.support.test.filters.SmallTest;
26 import android.support.test.runner.AndroidJUnit4;
27 import android.test.AndroidTestCase;
28 
29 import com.android.documentsui.R;
30 import com.android.documentsui.base.DocumentInfo;
31 import com.android.documentsui.base.RootInfo;
32 import com.android.documentsui.base.State;
33 import com.android.documentsui.dirlist.TestContext;
34 import com.android.documentsui.dirlist.TestData;
35 import com.android.documentsui.selection.SelectionManager;
36 import com.android.documentsui.testing.SelectionManagers;
37 import com.android.documentsui.testing.TestDirectoryDetails;
38 import com.android.documentsui.testing.TestEnv;
39 import com.android.documentsui.testing.TestFeatures;
40 import com.android.documentsui.testing.TestMenu;
41 import com.android.documentsui.testing.TestMenuInflater;
42 import com.android.documentsui.testing.TestMenuItem;
43 import com.android.documentsui.testing.TestScopedPreferences;
44 import com.android.documentsui.testing.TestSearchViewManager;
45 import com.android.documentsui.testing.TestSelectionDetails;
46 
47 import org.junit.Before;
48 import org.junit.Test;
49 import org.junit.runner.RunWith;
50 
51 @RunWith(AndroidJUnit4.class)
52 @SmallTest
53 public final class MenuManagerTest {
54 
55     private TestMenu testMenu;
56     private TestMenuItem rename;
57     private TestMenuItem selectAll;
58     private TestMenuItem moveTo;
59     private TestMenuItem copyTo;
60     private TestMenuItem compress;
61     private TestMenuItem extractTo;
62     private TestMenuItem share;
63     private TestMenuItem delete;
64     private TestMenuItem createDir;
65     private TestMenuItem settings;
66     private TestMenuItem newWindow;
67     private TestMenuItem open;
68     private TestMenuItem openWith;
69     private TestMenuItem openInNewWindow;
70     private TestMenuItem cut;
71     private TestMenuItem copy;
72     private TestMenuItem paste;
73     private TestMenuItem pasteInto;
74     private TestMenuItem advanced;
75     private TestMenuItem eject;
76     private TestMenuItem view;
77     private TestMenuItem debug;
78 
79     private TestFeatures features;
80     private TestSelectionDetails selectionDetails;
81     private TestDirectoryDetails dirDetails;
82     private TestSearchViewManager testSearchManager;
83     private TestScopedPreferences preferences;
84     private RootInfo testRootInfo;
85     private DocumentInfo testDocInfo;
86     private State state = new State();
87     private MenuManager mgr;
88     private TestActivity activity = TestActivity.create(TestEnv.create());
89     private SelectionManager selectionManager;
90 
91     @Before
setUp()92     public void setUp() {
93         testMenu = TestMenu.create();
94         rename = testMenu.findItem(R.id.menu_rename);
95         selectAll = testMenu.findItem(R.id.menu_select_all);
96         moveTo = testMenu.findItem(R.id.menu_move_to);
97         copyTo = testMenu.findItem(R.id.menu_copy_to);
98         compress = testMenu.findItem(R.id.menu_compress);
99         extractTo = testMenu.findItem(R.id.menu_extract_to);
100         share = testMenu.findItem(R.id.menu_share);
101         delete = testMenu.findItem(R.id.menu_delete);
102         createDir = testMenu.findItem(R.id.menu_create_dir);
103         settings = testMenu.findItem(R.id.menu_settings);
104         newWindow = testMenu.findItem(R.id.menu_new_window);
105         open = testMenu.findItem(R.id.menu_open);
106         openWith = testMenu.findItem(R.id.menu_open_with);
107         openInNewWindow = testMenu.findItem(R.id.menu_open_in_new_window);
108         cut = testMenu.findItem(R.id.menu_cut_to_clipboard);
109         copy = testMenu.findItem(R.id.menu_copy_to_clipboard);
110         paste = testMenu.findItem(R.id.menu_paste_from_clipboard);
111         pasteInto = testMenu.findItem(R.id.menu_paste_into_folder);
112         advanced = testMenu.findItem(R.id.menu_advanced);
113         eject = testMenu.findItem(R.id.menu_eject_root);
114         view = testMenu.findItem(R.id.menu_view_in_owner);
115         debug = testMenu.findItem(R.id.menu_debug);
116 
117         features = new TestFeatures();
118 
119         // These items by default are visible
120         testMenu.findItem(R.id.menu_select_all).setVisible(true);
121         testMenu.findItem(R.id.menu_list).setVisible(true);
122 
123         selectionDetails = new TestSelectionDetails();
124         dirDetails = new TestDirectoryDetails();
125         testSearchManager = new TestSearchViewManager();
126         preferences = new TestScopedPreferences();
127         selectionManager = SelectionManagers.createTestInstance(TestData.create(1));
128         selectionManager.toggleSelection("0");
129 
130         mgr = new MenuManager(
131                 features,
132                 testSearchManager,
133                 state,
134                 dirDetails,
135                 activity,
136                 selectionManager,
137                 this::getApplicationNameFromAuthority,
138                 this::getUriFromModelId);
139 
140         testRootInfo = new RootInfo();
141         testDocInfo = new DocumentInfo();
142     }
143 
getUriFromModelId(String id)144     private Uri getUriFromModelId(String id) {
145         return Uri.EMPTY;
146     }
getApplicationNameFromAuthority(String authority)147     private String getApplicationNameFromAuthority(String authority) {
148         return "TestApp";
149     }
150 
151     @Test
testActionMenu()152     public void testActionMenu() {
153         selectionDetails.canDelete = true;
154         selectionDetails.canRename = true;
155         dirDetails.canCreateDoc = true;
156 
157         mgr.updateActionMenu(testMenu, selectionDetails);
158 
159         rename.assertEnabled();
160         delete.assertVisible();
161         share.assertVisible();
162         copyTo.assertEnabled();
163         compress.assertEnabled();
164         extractTo.assertInvisible();
165         moveTo.assertEnabled();
166         view.assertInvisible();
167     }
168 
169     @Test
testActionMenu_ContainsPartial()170     public void testActionMenu_ContainsPartial() {
171         selectionDetails.containPartial = true;
172         dirDetails.canCreateDoc = true;
173         mgr.updateActionMenu(testMenu, selectionDetails);
174 
175         rename.assertDisabled();
176         share.assertInvisible();
177         copyTo.assertDisabled();
178         compress.assertDisabled();
179         extractTo.assertDisabled();
180         moveTo.assertDisabled();
181         view.assertInvisible();
182     }
183 
184     @Test
testActionMenu_CreateArchives_ReflectsFeatureState()185     public void testActionMenu_CreateArchives_ReflectsFeatureState() {
186         features.archiveCreation = false;
187         dirDetails.canCreateDoc = true;
188         mgr.updateActionMenu(testMenu, selectionDetails);
189 
190         compress.assertInvisible();
191         compress.assertDisabled();
192     }
193 
194     @Test
testActionMenu_CreateArchive()195     public void testActionMenu_CreateArchive() {
196         dirDetails.canCreateDoc = true;
197         mgr.updateActionMenu(testMenu, selectionDetails);
198 
199         compress.assertEnabled();
200     }
201 
202     @Test
testActionMenu_NoCreateArchive()203     public void testActionMenu_NoCreateArchive() {
204         dirDetails.canCreateDoc = false;
205         mgr.updateActionMenu(testMenu, selectionDetails);
206 
207         compress.assertDisabled();
208     }
209 
210     @Test
testActionMenu_cantRename()211     public void testActionMenu_cantRename() {
212         selectionDetails.canRename = false;
213         mgr.updateActionMenu(testMenu, selectionDetails);
214 
215         rename.assertDisabled();
216     }
217 
218     @Test
testActionMenu_cantDelete()219     public void testActionMenu_cantDelete() {
220         selectionDetails.canDelete = false;
221         mgr.updateActionMenu(testMenu, selectionDetails);
222 
223         delete.assertInvisible();
224         // We shouldn't be able to move files if we can't delete them
225         moveTo.assertDisabled();
226     }
227 
228     @Test
testActionsMenu_canViewInOwner()229     public void testActionsMenu_canViewInOwner() {
230         selectionDetails.canViewInOwner = true;
231         mgr.updateActionMenu(testMenu, selectionDetails);
232 
233         view.assertVisible();
234     }
235 
236     @Test
testActionMenu_changeToCanDelete()237     public void testActionMenu_changeToCanDelete() {
238         selectionDetails.canDelete = false;
239         mgr.updateActionMenu(testMenu, selectionDetails);
240 
241         selectionDetails.canDelete = true;
242         mgr.updateActionMenu(testMenu, selectionDetails);
243 
244         delete.assertVisible();
245         delete.assertEnabled();
246         moveTo.assertVisible();
247         moveTo.assertEnabled();
248     }
249 
250     @Test
testActionMenu_ContainsDirectory()251     public void testActionMenu_ContainsDirectory() {
252         selectionDetails.containDirectories = true;
253         mgr.updateActionMenu(testMenu, selectionDetails);
254 
255         // We can't share directories
256         share.assertInvisible();
257     }
258 
259     @Test
testActionMenu_RemovesDirectory()260     public void testActionMenu_RemovesDirectory() {
261         selectionDetails.containDirectories = true;
262         mgr.updateActionMenu(testMenu, selectionDetails);
263 
264         selectionDetails.containDirectories = false;
265         mgr.updateActionMenu(testMenu, selectionDetails);
266 
267         share.assertVisible();
268         share.assertEnabled();
269     }
270 
271     @Test
testActionMenu_CantExtract()272     public void testActionMenu_CantExtract() {
273         selectionDetails.canExtract = false;
274         mgr.updateActionMenu(testMenu, selectionDetails);
275 
276         extractTo.assertInvisible();
277     }
278 
279     @Test
testActionMenu_CanExtract_hidesCopyToAndCompressAndShare()280     public void testActionMenu_CanExtract_hidesCopyToAndCompressAndShare() {
281         features.archiveCreation = true;
282         selectionDetails.canExtract = true;
283         dirDetails.canCreateDoc = true;
284         mgr.updateActionMenu(testMenu, selectionDetails);
285 
286         extractTo.assertEnabled();
287         copyTo.assertDisabled();
288         compress.assertDisabled();
289     }
290 
291     @Test
testActionMenu_CanOpenWith()292     public void testActionMenu_CanOpenWith() {
293         selectionDetails.canOpenWith = true;
294         mgr.updateActionMenu(testMenu, selectionDetails);
295 
296         openWith.assertVisible();
297         openWith.assertEnabled();
298     }
299 
300     @Test
testActionMenu_NoOpenWith()301     public void testActionMenu_NoOpenWith() {
302         selectionDetails.canOpenWith = false;
303         mgr.updateActionMenu(testMenu, selectionDetails);
304 
305         openWith.assertVisible();
306         openWith.assertDisabled();
307     }
308 
309     @Test
testOptionMenu()310     public void testOptionMenu() {
311         mgr.updateOptionMenu(testMenu);
312 
313         advanced.assertInvisible();
314         advanced.assertTitle(R.string.menu_advanced_show);
315         createDir.assertDisabled();
316         debug.assertInvisible();
317         assertTrue(testSearchManager.updateMenuCalled());
318     }
319 
320     @Test
testOptionMenu_ShowAdvanced()321     public void testOptionMenu_ShowAdvanced() {
322         state.showAdvanced = true;
323         state.showDeviceStorageOption = true;
324         mgr.updateOptionMenu(testMenu);
325 
326         advanced.assertVisible();
327         advanced.assertTitle(R.string.menu_advanced_hide);
328     }
329 
330     @Test
testOptionMenu_CanCreateDirectory()331     public void testOptionMenu_CanCreateDirectory() {
332         dirDetails.canCreateDirectory = true;
333         mgr.updateOptionMenu(testMenu);
334 
335         createDir.assertEnabled();
336     }
337 
338     @Test
testOptionMenu_HasRootSettings()339     public void testOptionMenu_HasRootSettings() {
340         dirDetails.hasRootSettings = true;
341         mgr.updateOptionMenu(testMenu);
342 
343         settings.assertVisible();
344     }
345 
346     @Test
testInflateContextMenu_Files()347     public void testInflateContextMenu_Files() {
348         TestMenuInflater inflater = new TestMenuInflater();
349 
350         selectionDetails.containFiles = true;
351         selectionDetails.containDirectories = false;
352         mgr.inflateContextMenuForDocs(testMenu, inflater, selectionDetails);
353 
354         assertEquals(R.menu.file_context_menu, inflater.lastInflatedMenuId);
355     }
356 
357     @Test
testInflateContextMenu_Dirs()358     public void testInflateContextMenu_Dirs() {
359         TestMenuInflater inflater = new TestMenuInflater();
360 
361         selectionDetails.containFiles = false;
362         selectionDetails.containDirectories = true;
363         mgr.inflateContextMenuForDocs(testMenu, inflater, selectionDetails);
364 
365         assertEquals(R.menu.dir_context_menu, inflater.lastInflatedMenuId);
366     }
367 
368     @Test
testInflateContextMenu_Mixed()369     public void testInflateContextMenu_Mixed() {
370         TestMenuInflater inflater = new TestMenuInflater();
371 
372         selectionDetails.containFiles = true;
373         selectionDetails.containDirectories = true;
374         mgr.inflateContextMenuForDocs(testMenu, inflater, selectionDetails);
375 
376         assertEquals(R.menu.mixed_context_menu, inflater.lastInflatedMenuId);
377     }
378 
379     @Test
testContextMenu_EmptyArea()380     public void testContextMenu_EmptyArea() {
381         mgr.updateContextMenuForContainer(testMenu);
382 
383         selectAll.assertVisible();
384         selectAll.assertEnabled();
385         paste.assertVisible();
386         paste.assertDisabled();
387         createDir.assertVisible();
388         createDir.assertDisabled();
389     }
390 
391     @Test
testContextMenu_EmptyArea_NoItemToPaste()392     public void testContextMenu_EmptyArea_NoItemToPaste() {
393         dirDetails.hasItemsToPaste = false;
394         dirDetails.canCreateDoc = true;
395 
396         mgr.updateContextMenuForContainer(testMenu);
397 
398         selectAll.assertVisible();
399         selectAll.assertEnabled();
400         paste.assertVisible();
401         paste.assertDisabled();
402         createDir.assertVisible();
403         createDir.assertDisabled();
404     }
405 
406     @Test
testContextMenu_EmptyArea_CantCreateDoc()407     public void testContextMenu_EmptyArea_CantCreateDoc() {
408         dirDetails.hasItemsToPaste = true;
409         dirDetails.canCreateDoc = false;
410 
411         mgr.updateContextMenuForContainer(testMenu);
412 
413         selectAll.assertVisible();
414         selectAll.assertEnabled();
415         paste.assertVisible();
416         paste.assertDisabled();
417         createDir.assertVisible();
418         createDir.assertDisabled();
419     }
420 
421     @Test
testContextMenu_EmptyArea_CanPaste()422     public void testContextMenu_EmptyArea_CanPaste() {
423         dirDetails.hasItemsToPaste = true;
424         dirDetails.canCreateDoc = true;
425 
426         mgr.updateContextMenuForContainer(testMenu);
427 
428         selectAll.assertVisible();
429         selectAll.assertEnabled();
430         paste.assertVisible();
431         paste.assertEnabled();
432         createDir.assertVisible();
433         createDir.assertDisabled();
434     }
435 
436     @Test
testContextMenu_EmptyArea_CanCreateDirectory()437     public void testContextMenu_EmptyArea_CanCreateDirectory() {
438         dirDetails.canCreateDirectory = true;
439 
440         mgr.updateContextMenuForContainer(testMenu);
441 
442         selectAll.assertVisible();
443         selectAll.assertEnabled();
444         paste.assertVisible();
445         paste.assertDisabled();
446         createDir.assertVisible();
447         createDir.assertEnabled();
448     }
449 
450     @Test
testContextMenu_OnFile()451     public void testContextMenu_OnFile() {
452         selectionDetails.size = 1;
453         mgr.updateContextMenuForFiles(testMenu, selectionDetails);
454         open.assertVisible();
455         open.assertEnabled();
456         cut.assertVisible();
457         copy.assertVisible();
458         rename.assertVisible();
459         createDir.assertVisible();
460         delete.assertVisible();
461     }
462 
463     @Test
testContextMenu_OnFile_CanOpenWith()464     public void testContextMenu_OnFile_CanOpenWith() {
465         selectionDetails.canOpenWith = true;
466         mgr.updateContextMenuForFiles(testMenu, selectionDetails);
467         openWith.assertVisible();
468         openWith.assertEnabled();
469     }
470 
471     @Test
testContextMenu_OnFile_NoOpenWith()472     public void testContextMenu_OnFile_NoOpenWith() {
473         selectionDetails.canOpenWith = false;
474         mgr.updateContextMenuForFiles(testMenu, selectionDetails);
475         openWith.assertVisible();
476         openWith.assertDisabled();
477     }
478 
479     @Test
testContextMenu_OnMultipleFiles()480     public void testContextMenu_OnMultipleFiles() {
481         selectionDetails.size = 3;
482         mgr.updateContextMenuForFiles(testMenu, selectionDetails);
483         open.assertVisible();
484         open.assertDisabled();
485     }
486 
487     @Test
testContextMenu_OnWritableDirectory()488     public void testContextMenu_OnWritableDirectory() {
489         selectionDetails.size = 1;
490         selectionDetails.canPasteInto = true;
491         dirDetails.hasItemsToPaste = true;
492         mgr.updateContextMenuForDirs(testMenu, selectionDetails);
493         openInNewWindow.assertVisible();
494         openInNewWindow.assertEnabled();
495         cut.assertVisible();
496         copy.assertVisible();
497         pasteInto.assertVisible();
498         pasteInto.assertEnabled();
499         rename.assertVisible();
500         delete.assertVisible();
501     }
502 
503     @Test
testContextMenu_OnNonWritableDirectory()504     public void testContextMenu_OnNonWritableDirectory() {
505         selectionDetails.size = 1;
506         selectionDetails.canPasteInto = false;
507         mgr.updateContextMenuForDirs(testMenu, selectionDetails);
508         openInNewWindow.assertVisible();
509         openInNewWindow.assertEnabled();
510         cut.assertVisible();
511         copy.assertVisible();
512         pasteInto.assertVisible();
513         pasteInto.assertDisabled();
514         rename.assertVisible();
515         delete.assertVisible();
516     }
517 
518     @Test
testContextMenu_OnWritableDirectory_NothingToPaste()519     public void testContextMenu_OnWritableDirectory_NothingToPaste() {
520         selectionDetails.canPasteInto = true;
521         selectionDetails.size = 1;
522         dirDetails.hasItemsToPaste = false;
523         mgr.updateContextMenuForDirs(testMenu, selectionDetails);
524         pasteInto.assertVisible();
525         pasteInto.assertDisabled();
526     }
527 
528     @Test
testContextMenu_OnMultipleDirectories()529     public void testContextMenu_OnMultipleDirectories() {
530         selectionDetails.size = 3;
531         mgr.updateContextMenuForDirs(testMenu, selectionDetails);
532         openInNewWindow.assertVisible();
533         openInNewWindow.assertDisabled();
534     }
535 
536     @Test
testContextMenu_OnMixedDocs()537     public void testContextMenu_OnMixedDocs() {
538         selectionDetails.containDirectories = true;
539         selectionDetails.containFiles = true;
540         selectionDetails.size = 2;
541         selectionDetails.canDelete = true;
542         mgr.updateContextMenu(testMenu, selectionDetails);
543         cut.assertVisible();
544         cut.assertEnabled();
545         copy.assertVisible();
546         copy.assertEnabled();
547         delete.assertVisible();
548         delete.assertEnabled();
549     }
550 
551     @Test
testContextMenu_OnMixedDocs_hasPartialFile()552     public void testContextMenu_OnMixedDocs_hasPartialFile() {
553         selectionDetails.containDirectories = true;
554         selectionDetails.containFiles = true;
555         selectionDetails.size = 2;
556         selectionDetails.containPartial = true;
557         selectionDetails.canDelete = true;
558         mgr.updateContextMenu(testMenu, selectionDetails);
559         cut.assertVisible();
560         cut.assertDisabled();
561         copy.assertVisible();
562         copy.assertDisabled();
563         delete.assertVisible();
564         delete.assertEnabled();
565     }
566 
567     @Test
testContextMenu_OnMixedDocs_hasUndeletableFile()568     public void testContextMenu_OnMixedDocs_hasUndeletableFile() {
569         selectionDetails.containDirectories = true;
570         selectionDetails.containFiles = true;
571         selectionDetails.size = 2;
572         selectionDetails.canDelete = false;
573         mgr.updateContextMenu(testMenu, selectionDetails);
574         cut.assertVisible();
575         cut.assertDisabled();
576         copy.assertVisible();
577         copy.assertEnabled();
578         delete.assertVisible();
579         delete.assertDisabled();
580     }
581 
582     @Test
testRootContextMenu()583     public void testRootContextMenu() {
584         testRootInfo.flags = Root.FLAG_SUPPORTS_CREATE;
585 
586         mgr.updateRootContextMenu(testMenu, testRootInfo, testDocInfo);
587 
588         eject.assertInvisible();
589 
590         openInNewWindow.assertVisible();
591         openInNewWindow.assertEnabled();
592 
593         pasteInto.assertVisible();
594         pasteInto.assertDisabled();
595 
596         settings.assertVisible();
597         settings.assertDisabled();
598     }
599 
600     @Test
testRootContextMenu_HasRootSettings()601     public void testRootContextMenu_HasRootSettings() {
602         testRootInfo.flags = Root.FLAG_HAS_SETTINGS;
603         mgr.updateRootContextMenu(testMenu, testRootInfo, testDocInfo);
604 
605         settings.assertEnabled();
606     }
607 
608     @Test
testRootContextMenu_NonWritableRoot()609     public void testRootContextMenu_NonWritableRoot() {
610         dirDetails.hasItemsToPaste = true;
611         mgr.updateRootContextMenu(testMenu, testRootInfo, testDocInfo);
612 
613         pasteInto.assertVisible();
614         pasteInto.assertDisabled();
615     }
616 
617     @Test
testRootContextMenu_NothingToPaste()618     public void testRootContextMenu_NothingToPaste() {
619         testRootInfo.flags = Root.FLAG_SUPPORTS_CREATE;
620         testDocInfo.flags = Document.FLAG_DIR_SUPPORTS_CREATE;
621         dirDetails.hasItemsToPaste = false;
622         mgr.updateRootContextMenu(testMenu, testRootInfo, testDocInfo);
623 
624         pasteInto.assertVisible();
625         pasteInto.assertDisabled();
626     }
627 
628     @Test
testRootContextMenu_PasteIntoWritableRoot()629     public void testRootContextMenu_PasteIntoWritableRoot() {
630         testRootInfo.flags = Root.FLAG_SUPPORTS_CREATE;
631         testDocInfo.flags = Document.FLAG_DIR_SUPPORTS_CREATE;
632         dirDetails.hasItemsToPaste = true;
633         mgr.updateRootContextMenu(testMenu, testRootInfo, testDocInfo);
634 
635         pasteInto.assertVisible();
636         pasteInto.assertEnabled();
637     }
638 
639     @Test
testRootContextMenu_Eject()640     public void testRootContextMenu_Eject() {
641         testRootInfo.flags = Root.FLAG_SUPPORTS_EJECT;
642         mgr.updateRootContextMenu(testMenu, testRootInfo, testDocInfo);
643 
644         eject.assertEnabled();
645     }
646 
647     @Test
testRootContextMenu_EjectInProcess()648     public void testRootContextMenu_EjectInProcess() {
649         testRootInfo.flags = Root.FLAG_SUPPORTS_EJECT;
650         testRootInfo.ejecting = true;
651         mgr.updateRootContextMenu(testMenu, testRootInfo, testDocInfo);
652 
653         eject.assertDisabled();
654     }
655 }
656