Cleanup for removal of ImageAttributes from public API
[platform/core/uifw/dali-adaptor.git] / automated-tests / src / dali-platform-abstraction / utc-image-loading-cancel-some-loads.cpp
1 /*
2  * Copyright (c) 2014 Samsung Electronics Co., Ltd.
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
18 #include "utc-image-loading-common.h"
19
20 void utc_image_loading_cancel_some_loads_startup(void)
21 {
22   utc_dali_loading_startup();
23 }
24
25 void utc_image_loading_cancel_some_loads_cleanup(void)
26 {
27   utc_dali_loading_cleanup();
28 }
29
30 /**
31  * @brief Test case for load cancellation.
32  *
33  * Load lots, cancel a subset and be sure the wrong loads are never cancelled
34  * and that all loads issued are either completed or cancelled.
35  */
36 int UtcDaliCancelSomeLoads(void)
37 {
38   tet_printf( "Running load cancel load subset test.\n" );
39
40   DALI_ASSERT_ALWAYS( gAbstraction != 0 );
41
42   // Start a bunch of loads that should work:
43
44   Dali::Integration::LoadResourcePriority priority = LoadPriorityNormal;
45   unsigned loadsLaunched = 0;
46
47   std::set<Integration::ResourceId> cancelledLoadSet;
48   Dali::Internal::Platform::ResourceCollector resourceSink;
49
50   for( unsigned loadGroup = 0; loadGroup < NUM_LOAD_GROUPS_TO_ISSUE; ++loadGroup )
51   {
52     const unsigned preIterationCompletions = resourceSink.mGrandTotalCompletions;
53
54     // Issue load requests for a batch of images:
55     for( unsigned validImage = 0; validImage < NUM_VALID_IMAGES; ++validImage )
56     {
57       const ImageAttributes & loadParams = gCancelAttributes[ loadsLaunched % gCancelAttributes.size() ];
58       const BitmapResourceType bitmapResourceType( loadParams.first, loadParams.second.first, loadParams.second.second.first, loadParams.second.second.second );
59       const ResourceId resourceId = loadGroup * NUM_VALID_IMAGES + validImage + 1;
60       gAbstraction->LoadResource( ResourceRequest( resourceId, bitmapResourceType, VALID_IMAGES[validImage], priority ) );
61       loadsLaunched += 1;
62     }
63
64     // Let the first image in the batch start to load so we can try to cancel it in-flight:
65     usleep( 1 * 1000 ); //< 1 ms is enough to let an image start to load.
66     ///@Note: The log should show cancellations of many in-flight loads in desktop builds with info-level logging enabled (e.g., "INFO: DALI: : CheckForCancellation: Cancelled in-flight resource (21)."). If it doesn't, the above delay may need to be adjusted.
67
68     // Cancel just two loads (hopefully one in-flight and one queued):
69
70     // Cancel first load, hopefully while it is in-flight:
71     const ResourceId cancelledInFlight = loadGroup * NUM_VALID_IMAGES + 1;
72     gAbstraction->CancelLoad( cancelledInFlight, ResourceBitmap );
73     cancelledLoadSet.insert( cancelledInFlight );
74
75     // Cancel second load, that is still queued:
76     const ResourceId cancelledFromQueue = loadGroup * NUM_VALID_IMAGES + NUM_VALID_IMAGES;
77     gAbstraction->CancelLoad( cancelledFromQueue, ResourceBitmap );
78     cancelledLoadSet.insert( cancelledFromQueue );
79
80     // Drain a group worth of images so the cancellations hit in-flight loads on the next iteration:
81     for( unsigned i = 0; i < NUM_VALID_IMAGES * 1000 * 1000 * 10 / (5 * 1000)  && resourceSink.mGrandTotalCompletions < preIterationCompletions + NUM_VALID_IMAGES - 2; ++i )
82     {
83       gAbstraction->GetResources( resourceSink );
84       usleep( 5 * 1000 );
85     }
86   }
87
88   // Drain any spare completed loads until no new loads complete on an iteration:
89   unsigned lastNotifications = -1;
90   for( unsigned i = 0; i < MAX_NUM_RESOURCE_TRIES && resourceSink.mGrandTotalCompletions < loadsLaunched && resourceSink.mGrandTotalNotifications != lastNotifications; ++i )
91   {
92     lastNotifications = resourceSink.mGrandTotalNotifications;
93     gAbstraction->GetResources( resourceSink );
94     usleep( 70 * 1000 ); //< 70 ms should allow at least one medium image to load. You  might to increase this to run on a slow device.
95     gAbstraction->GetResources( resourceSink );
96     usleep( 70 * 1000 );
97     gAbstraction->GetResources( resourceSink );
98     usleep( 70 * 1000 );
99     gAbstraction->GetResources( resourceSink );
100   }
101
102   // Check the loads completed as expected:
103
104   tet_printf( "Issued Loads: %u, Completed Loads: %u, Successful Loads: %u, Failed Loads: %u \n", loadsLaunched, resourceSink.mGrandTotalCompletions, unsigned(resourceSink.mSuccessCounts.size()), unsigned(resourceSink.mFailureCounts.size()) );
105   DALI_TEST_CHECK( loadsLaunched >= resourceSink.mGrandTotalCompletions );
106   DALI_TEST_CHECK( loadsLaunched >= resourceSink.mSuccessCounts.size() );
107   DALI_TEST_CHECK( 0 == resourceSink.mFailureCounts.size() );
108
109   // Check that if an image was not loaded, it is one of the ones that was cancelled:
110   // This is the main point of this test case.
111   std::vector<Integration::ResourceId> missingLoads;
112   for( unsigned resourceId = 1; resourceId <= NUM_LOAD_GROUPS_TO_ISSUE * NUM_VALID_IMAGES; ++resourceId )
113   {
114     // Was the load (not) completed?
115     if( resourceSink.mCompletionStatuses.find( resourceId ) == resourceSink.mCompletionStatuses.end() )
116     {
117       // Was the load (not) cancelled?
118       if( cancelledLoadSet.find( resourceId ) == cancelledLoadSet.end() )
119       {
120         // Whoa, the load was not completed and not cancelled either... so where did it go then?
121         missingLoads.push_back( resourceId );
122         tet_printf( "Missing load. ResourceId %u was not completed but was also not cancelled.\n", resourceId );
123         ///@note If this fires, you are probably not waiting long enough in the draining loop above (usleep( 70 * 1000 );).
124       }
125     }
126   }
127   DALI_TEST_CHECK( missingLoads.size() == 0U );
128
129   // Check that each success was reported exactly once:
130   for(ResourceCounterMap::const_iterator it = resourceSink.mSuccessCounts.begin(), end = resourceSink.mSuccessCounts.end(); it != end; ++it )
131   {
132     DALI_TEST_CHECK( it->second == 1u );
133   }
134
135   END_TEST;
136 }