1/*
2 * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16// gtest
17#include <gtest/gtest.h>
18#include <ability_context.h>
19#include "window.h"
20#include "window_option.h"
21#include "window_scene.h"
22#include "wm_common.h"
23
24using namespace testing;
25using namespace testing::ext;
26
27namespace OHOS {
28namespace Rosen {
29class WindowSubWindowTest : public testing::Test {
30public:
31    static void SetUpTestCase();
32    static void TearDownTestCase();
33    virtual void SetUp() override;
34    virtual void TearDown() override;
35};
36
37void WindowSubWindowTest::SetUpTestCase()
38{
39}
40
41void WindowSubWindowTest::TearDownTestCase()
42{
43}
44
45void WindowSubWindowTest::SetUp()
46{
47}
48
49void WindowSubWindowTest::TearDown()
50{
51}
52
53static sptr<WindowScene> CreateWindowScene()
54{
55    sptr<IWindowLifeCycle> listener = nullptr;
56    std::shared_ptr<AbilityRuntime::AbilityContext> abilityContext = nullptr;
57
58    sptr<WindowScene> scene = new WindowScene();
59    scene->Init(0, abilityContext, listener);
60    return scene;
61}
62
63static sptr<Window> CreateSubWindow(sptr<WindowScene> scene, WindowType type,
64    struct Rect rect, uint32_t flags, std::string name = "")
65{
66    sptr<WindowOption> subOp = new WindowOption();
67    subOp->SetWindowType(type);
68    subOp->SetWindowMode(WindowMode::WINDOW_MODE_FLOATING);
69    subOp->SetWindowRect(rect);
70    subOp->SetWindowFlags(flags);
71
72    static int cnt = 0;
73    std::string subWinName = (name == "") ? "SubWindow" + std::to_string(cnt++) : name;
74
75    return scene->CreateWindow(subWinName, subOp);
76}
77
78/**
79 * @tc.name: SubWindow01
80 * @tc.desc: FullScreen Main Window + Floating SubWindow
81 * @tc.type: FUNC
82 */
83HWTEST_F(WindowSubWindowTest, SubWindow01, Function | MediumTest | Level2)
84{
85    sptr<WindowScene> scene = CreateWindowScene();
86
87    struct Rect rect = {0, 0, 100, 200};
88    uint32_t flags = 0;
89    sptr<Window> subWindow = CreateSubWindow(scene, WindowType::WINDOW_TYPE_APP_SUB_WINDOW, rect, flags);
90    if (subWindow == nullptr) {
91        return;
92    }
93    ASSERT_NE(nullptr, subWindow);
94
95    ASSERT_EQ(WMError::WM_OK, scene->GoForeground());
96    ASSERT_EQ(WMError::WM_OK, subWindow->Show());
97
98    ASSERT_EQ(WMError::WM_OK, subWindow->Hide());
99    ASSERT_EQ(WMError::WM_OK, scene->GoBackground());
100    sleep(1);
101
102    subWindow->Destroy();
103    scene->GoDestroy();
104}
105
106/**
107 * @tc.name: SubWindow02
108 * @tc.desc: FullScreen Main Window + Floating SubWindow & Parent Limit work
109 * @tc.type: FUNC
110 */
111HWTEST_F(WindowSubWindowTest, SubWindow02, Function | MediumTest | Level2)
112{
113    sptr<WindowScene> scene = CreateWindowScene();
114
115    struct Rect rect = {0, 0, 100, 200};
116    uint32_t flags = static_cast<uint32_t>(WindowFlag::WINDOW_FLAG_PARENT_LIMIT);
117    sptr<Window> subWindow = CreateSubWindow(scene, WindowType::WINDOW_TYPE_APP_SUB_WINDOW, rect, flags);
118    if (subWindow == nullptr) {
119        return;
120    }
121    ASSERT_NE(nullptr, subWindow);
122
123    ASSERT_EQ(WMError::WM_OK, scene->GoForeground());
124    ASSERT_EQ(WMError::WM_OK, subWindow->Show());
125
126    ASSERT_EQ(WMError::WM_OK, subWindow->Hide());
127    ASSERT_EQ(WMError::WM_OK, scene->GoBackground());
128    sleep(1);
129
130    subWindow->Destroy();
131    scene->GoDestroy();
132}
133
134/**
135 * @tc.name: SubWindow03
136 * @tc.desc: FullScreen Main Window + Floating MediaWindow
137 * @tc.type: FUNC
138 */
139HWTEST_F(WindowSubWindowTest, SubWindow03, Function | MediumTest | Level2)
140{
141    sptr<WindowScene> scene = CreateWindowScene();
142
143    struct Rect rect = {0, 2000, 100, 200};
144    uint32_t flags = static_cast<uint32_t>(WindowFlag::WINDOW_FLAG_PARENT_LIMIT);
145    sptr<Window> subWindow = CreateSubWindow(scene, WindowType::WINDOW_TYPE_MEDIA, rect, flags);
146    if (subWindow == nullptr) {
147        return;
148    }
149    ASSERT_NE(nullptr, subWindow);
150
151    ASSERT_EQ(WMError::WM_OK, scene->GoForeground());
152    ASSERT_EQ(WMError::WM_OK, subWindow->Show());
153
154    ASSERT_EQ(WMError::WM_OK, subWindow->Hide());
155    ASSERT_EQ(WMError::WM_OK, scene->GoBackground());
156    sleep(1);
157
158    subWindow->Destroy();
159    scene->GoDestroy();
160}
161
162/**
163 * @tc.name: SubWindow04
164 * @tc.desc: FullScreen Main Window + Floating MediaWindow
165 * @tc.type: FUNC
166 */
167HWTEST_F(WindowSubWindowTest, SubWindow04, Function | MediumTest | Level2)
168{
169    sptr<WindowScene> scene = CreateWindowScene();
170
171    struct Rect rect = {0, 2000, 3000, 2000};
172    uint32_t flags = static_cast<uint32_t>(WindowFlag::WINDOW_FLAG_PARENT_LIMIT);
173    sptr<Window> subWindow = CreateSubWindow(scene, WindowType::WINDOW_TYPE_MEDIA, rect, flags);
174    if (subWindow == nullptr) {
175        return;
176    }
177    ASSERT_NE(nullptr, subWindow);
178
179    ASSERT_EQ(WMError::WM_OK, scene->GoForeground());
180    ASSERT_EQ(WMError::WM_OK, subWindow->Show());
181
182    ASSERT_EQ(WMError::WM_OK, subWindow->Hide());
183    ASSERT_EQ(WMError::WM_OK, scene->GoBackground());
184    sleep(1);
185
186    subWindow->Destroy();
187    scene->GoDestroy();
188}
189
190/**
191 * @tc.name: SubWindow05
192 * @tc.desc: FullScreen Main Window + Floating MediaWindow + Floating SubWindow
193 * @tc.type: FUNC
194 */
195HWTEST_F(WindowSubWindowTest, SubWindow05, Function | MediumTest | Level3)
196{
197    sptr<WindowScene> scene = CreateWindowScene();
198
199    struct Rect rect = {0, 0, 100, 200};
200    uint32_t flags = static_cast<uint32_t>(WindowFlag::WINDOW_FLAG_PARENT_LIMIT);
201    sptr<Window> subWindow = CreateSubWindow(scene, WindowType::WINDOW_TYPE_MEDIA, rect, flags);
202    if (subWindow == nullptr) {
203        return;
204    }
205    ASSERT_NE(nullptr, subWindow);
206
207    sptr<Window> subWindow2 = CreateSubWindow(scene, WindowType::WINDOW_TYPE_APP_SUB_WINDOW, rect, flags);
208    ASSERT_NE(nullptr, subWindow2);
209
210    ASSERT_EQ(WMError::WM_OK, scene->GoForeground());
211    ASSERT_EQ(WMError::WM_OK, subWindow->Show());
212    ASSERT_EQ(WMError::WM_OK, subWindow2->Show());
213
214    ASSERT_EQ(WMError::WM_OK, subWindow->Hide());
215    ASSERT_EQ(WMError::WM_OK, subWindow2->Hide());
216    ASSERT_EQ(WMError::WM_OK, scene->GoBackground());
217    sleep(1);
218
219    subWindow->Destroy();
220    subWindow2->Destroy();
221    scene->GoDestroy();
222}
223
224/**
225 * @tc.name: SubWindow06
226 * @tc.desc: FullScreen Main Window + 2 SubWindows
227 * @tc.type: FUNC
228 */
229HWTEST_F(WindowSubWindowTest, SubWindow06, Function | MediumTest | Level3)
230{
231    sptr<WindowScene> scene = CreateWindowScene();
232
233    struct Rect rect = {0, 0, 100, 200};
234    sptr<Window> subWindow0 = CreateSubWindow(scene, WindowType::WINDOW_TYPE_APP_SUB_WINDOW, rect, 0);
235    if (subWindow0 == nullptr) {
236        return;
237    }
238    ASSERT_NE(nullptr, subWindow0);
239
240    sptr<Window> subWindow1 = CreateSubWindow(scene, WindowType::WINDOW_TYPE_APP_SUB_WINDOW, rect, 0);
241    ASSERT_NE(nullptr, subWindow1);
242
243    ASSERT_EQ(WMError::WM_OK, scene->GoForeground());
244    ASSERT_EQ(WMError::WM_OK, subWindow0->Show());
245    ASSERT_EQ(WMError::WM_OK, subWindow1->Show());
246
247    ASSERT_EQ(WMError::WM_OK, subWindow0->Hide());
248    ASSERT_EQ(WMError::WM_OK, subWindow1->Hide());
249    ASSERT_EQ(WMError::WM_OK, scene->GoBackground());
250    sleep(1);
251
252    subWindow0->Destroy();
253    subWindow1->Destroy();
254    scene->GoDestroy();
255}
256
257/**
258 * @tc.name: SubWindow07
259 * @tc.desc: FullScreen Main Window + Floating SubWindow & MainWindow First GoBackground
260 * @tc.type: FUNC
261 */
262HWTEST_F(WindowSubWindowTest, SubWindow07, Function | MediumTest | Level4)
263{
264    sptr<WindowScene> scene = CreateWindowScene();
265
266    struct Rect rect = {0, 0, 100, 200};
267    uint32_t flags = static_cast<uint32_t>(WindowFlag::WINDOW_FLAG_PARENT_LIMIT);
268    sptr<Window> subWindow = CreateSubWindow(scene, WindowType::WINDOW_TYPE_APP_SUB_WINDOW, rect, flags);
269    if (subWindow == nullptr) {
270        return;
271    }
272    ASSERT_NE(nullptr, subWindow);
273
274    ASSERT_EQ(WMError::WM_OK, scene->GoForeground());
275    ASSERT_EQ(WMError::WM_OK, subWindow->Show());
276
277    ASSERT_EQ(WMError::WM_OK, scene->GoBackground());
278    ASSERT_EQ(WMError::WM_OK, subWindow->Hide());
279    sleep(1);
280
281    subWindow->Destroy();
282    scene->GoDestroy();
283}
284
285/**
286 * @tc.name: SubWindow08
287 * @tc.desc: FullScreen Main Window + Floating SubWindow & only show SubWindow
288 * @tc.type: FUNC
289 */
290HWTEST_F(WindowSubWindowTest, SubWindow08, Function | MediumTest | Level4)
291{
292    sptr<WindowScene> scene = CreateWindowScene();
293
294    struct Rect rect = {0, 0, 100, 200};
295    uint32_t flags = static_cast<uint32_t>(WindowFlag::WINDOW_FLAG_PARENT_LIMIT);
296    sptr<Window> subWindow = CreateSubWindow(scene, WindowType::WINDOW_TYPE_APP_SUB_WINDOW, rect, flags);
297    if (subWindow == nullptr) {
298        return;
299    }
300    ASSERT_NE(nullptr, subWindow);
301
302    ASSERT_EQ(WMError::WM_ERROR_INVALID_PARAM, subWindow->Show());
303}
304
305/**
306 * @tc.name: SubWindow09
307 * @tc.desc: FullScreen Main Window + Floating SubWindow & first destroy SubWindow, then destroy MainWindow
308 * @tc.type: FUNC
309 */
310HWTEST_F(WindowSubWindowTest, SubWindow09, Function | MediumTest | Level2)
311{
312    sptr<WindowScene> scene = CreateWindowScene();
313
314    struct Rect rect = {0, 0, 100, 200};
315    uint32_t flags = static_cast<uint32_t>(WindowFlag::WINDOW_FLAG_PARENT_LIMIT);
316    sptr<Window> subWindow = CreateSubWindow(scene, WindowType::WINDOW_TYPE_APP_SUB_WINDOW, rect, flags);
317    if (subWindow == nullptr) {
318        return;
319    }
320    ASSERT_NE(nullptr, subWindow);
321
322    ASSERT_EQ(WMError::WM_OK, scene->GoForeground());
323    ASSERT_EQ(WMError::WM_OK, subWindow->Show());
324
325    ASSERT_EQ(WMError::WM_OK, subWindow->Hide());
326    ASSERT_EQ(WMError::WM_OK, scene->GoBackground());
327    sleep(1);
328
329    ASSERT_EQ(WMError::WM_OK, subWindow->Destroy());
330
331    subWindow->Destroy();
332    scene->GoDestroy();
333}
334
335/**
336 * @tc.name: SubWindow10
337 * @tc.desc: FullScreen Main Window + Floating SubWindow & first destroy MainWindow, then destroy SubWindow
338 * @tc.type: FUNC
339 */
340HWTEST_F(WindowSubWindowTest, SubWindow10, Function | MediumTest | Level2)
341{
342    sptr<WindowScene> scene = CreateWindowScene();
343
344    struct Rect rect = {0, 0, 100, 200};
345    uint32_t flags = static_cast<uint32_t>(WindowFlag::WINDOW_FLAG_PARENT_LIMIT);
346    sptr<Window> subWindow = CreateSubWindow(scene, WindowType::WINDOW_TYPE_APP_SUB_WINDOW, rect, flags);
347    if (subWindow == nullptr) {
348        return;
349    }
350    ASSERT_NE(nullptr, subWindow);
351
352    ASSERT_EQ(WMError::WM_OK, scene->GoForeground());
353    ASSERT_EQ(WMError::WM_OK, subWindow->Show());
354    sleep(1);
355
356    sptr<Window> mainWindow = scene->GetMainWindow();
357    ASSERT_EQ(WMError::WM_OK, mainWindow->Destroy());
358    ASSERT_EQ(WMError::WM_OK, subWindow->Destroy());
359
360    scene->GoDestroy();
361}
362
363/**
364 * @tc.name: SubWindow11
365 * @tc.desc: FullScreen Main Window + 5 subWindows
366 * @tc.type: FUNC
367 */
368HWTEST_F(WindowSubWindowTest, SubWindow11, Function | MediumTest | Level3)
369{
370    sptr<WindowScene> scene = CreateWindowScene();
371
372    struct Rect rect = {0, 0, 100, 200};
373    sptr<Window> subWindow0 = CreateSubWindow(scene, WindowType::WINDOW_TYPE_APP_SUB_WINDOW, rect, 0);
374    if (subWindow0 == nullptr) {
375        return;
376    }
377    ASSERT_NE(nullptr, subWindow0);
378
379    sptr<Window> subWindow1 = CreateSubWindow(scene, WindowType::WINDOW_TYPE_APP_SUB_WINDOW, rect, 0);
380    if (subWindow1 == nullptr) {
381        return;
382    }
383    ASSERT_NE(nullptr, subWindow1);
384
385    sptr<Window> subWindow2 = CreateSubWindow(scene, WindowType::WINDOW_TYPE_APP_SUB_WINDOW, rect, 0);
386    if (subWindow2 == nullptr) {
387        return;
388    }
389    ASSERT_NE(nullptr, subWindow2);
390
391    sptr<Window> subWindow3 = CreateSubWindow(scene, WindowType::WINDOW_TYPE_APP_SUB_WINDOW, rect, 0);
392    if (subWindow3 == nullptr) {
393        return;
394    }
395    ASSERT_NE(nullptr, subWindow3);
396
397    sptr<Window> subWindow4 = CreateSubWindow(scene, WindowType::WINDOW_TYPE_APP_SUB_WINDOW, rect, 0);
398    if (subWindow4 == nullptr) {
399        return;
400    }
401    ASSERT_NE(nullptr, subWindow4);
402    if (scene->GoForeground() == WMError::WM_OK) {
403        ASSERT_EQ(WMError::WM_OK, scene->GoForeground());
404    }
405
406    ASSERT_EQ(WMError::WM_OK, subWindow0->Show());
407    ASSERT_EQ(WMError::WM_OK, subWindow1->Show());
408    ASSERT_EQ(WMError::WM_OK, subWindow2->Show());
409    ASSERT_EQ(WMError::WM_OK, subWindow3->Show());
410    ASSERT_EQ(WMError::WM_OK, subWindow4->Show());
411
412    ASSERT_EQ(WMError::WM_OK, subWindow0->Hide());
413    ASSERT_EQ(WMError::WM_OK, subWindow1->Hide());
414    ASSERT_EQ(WMError::WM_OK, subWindow2->Hide());
415    ASSERT_EQ(WMError::WM_OK, subWindow3->Hide());
416    ASSERT_EQ(WMError::WM_OK, subWindow4->Hide());
417    ASSERT_EQ(WMError::WM_OK, scene->GoBackground());
418    sleep(1);
419
420    subWindow0->Destroy();
421    subWindow1->Destroy();
422    subWindow2->Destroy();
423    subWindow3->Destroy();
424    subWindow4->Destroy();
425    scene->GoDestroy();
426}
427
428/**
429 * @tc.name: SubWindow12
430 * @tc.desc: FullScreen Main Window + 2 SubWindows with the same name
431 * @tc.type: FUNC
432 */
433HWTEST_F(WindowSubWindowTest, SubWindow12, Function | MediumTest | Level3)
434{
435    sptr<WindowScene> scene = CreateWindowScene();
436
437    struct Rect rect = {0, 0, 100, 200};
438    sptr<Window> subWindow0 = CreateSubWindow(scene, WindowType::WINDOW_TYPE_APP_SUB_WINDOW, rect, 0, "sub0");
439    sptr<Window> subWindow1 = CreateSubWindow(scene, WindowType::WINDOW_TYPE_APP_SUB_WINDOW, rect, 0, "sub0");
440    if (subWindow0 == nullptr) {
441        return;
442    }
443    if (subWindow1 == nullptr) {
444        return;
445    }
446    ASSERT_NE(nullptr, subWindow0);
447    ASSERT_EQ(nullptr, subWindow1);
448
449    ASSERT_EQ(WMError::WM_OK, scene->GoForeground());
450    ASSERT_EQ(WMError::WM_OK, subWindow0->Show());
451
452    ASSERT_EQ(WMError::WM_OK, subWindow0->Hide());
453    ASSERT_EQ(WMError::WM_OK, scene->GoBackground());
454    sleep(1);
455
456    subWindow0->Destroy();
457    scene->GoDestroy();
458}
459
460/**
461 * @tc.name: SubWindow13
462 * @tc.desc: FullScreen Main Window + 2 subwindows with the same name but one create after another destroyed
463 * @tc.type: FUNC
464 */
465HWTEST_F(WindowSubWindowTest, SubWindow13, Function | MediumTest | Level3)
466{
467    sptr<WindowScene> scene = CreateWindowScene();
468    if (scene->GoForeground() == WMError::WM_OK) {
469        ASSERT_EQ(WMError::WM_OK, scene->GoForeground());
470    }
471
472    struct Rect rect = {0, 0, 100, 200};
473    sptr<Window> subWindow0 = CreateSubWindow(scene, WindowType::WINDOW_TYPE_APP_SUB_WINDOW, rect, 0, "sub1");
474    if (subWindow0 == nullptr) {
475        return;
476    }
477    ASSERT_NE(nullptr, subWindow0);
478    ASSERT_EQ(WMError::WM_OK, subWindow0->Show());
479    ASSERT_EQ(WMError::WM_OK, subWindow0->Destroy());
480
481    sptr<Window> subWindow1 = CreateSubWindow(scene, WindowType::WINDOW_TYPE_APP_SUB_WINDOW, rect, 0, "sub1");
482    if (subWindow1 == nullptr) {
483        return;
484    }
485    ASSERT_NE(nullptr, subWindow1);
486    ASSERT_EQ(WMError::WM_OK, subWindow1->Show());
487    ASSERT_EQ(WMError::WM_OK, subWindow1->Destroy());
488
489    ASSERT_EQ(WMError::WM_OK, scene->GoBackground());
490    sleep(1);
491    scene->GoDestroy();
492}
493} // namespace Rosen
494} // namespace OHOS
495