Milestone 5: deliver embedded RDP sessions and lifecycle hardening
This commit is contained in:
876
third_party/FreeRDP/libfreerdp/codec/test/TestFreeRDPRegion.c
vendored
Normal file
876
third_party/FreeRDP/libfreerdp/codec/test/TestFreeRDPRegion.c
vendored
Normal file
@@ -0,0 +1,876 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
*
|
||||
* Copyright 2014 Thincast Technologies GmbH
|
||||
* Copyright 2014 Hardening <contact@hardening-consulting.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/print.h>
|
||||
|
||||
#include <freerdp/codec/region.h>
|
||||
|
||||
static BOOL compareRectangles(const RECTANGLE_16* src1, const RECTANGLE_16* src2, int nb)
|
||||
{
|
||||
for (int i = 0; i < nb; i++, src1++, src2++)
|
||||
{
|
||||
if (memcmp(src1, src2, sizeof(RECTANGLE_16)) != 0)
|
||||
{
|
||||
(void)fprintf(stderr,
|
||||
"expecting rect %d (%" PRIu16 ",%" PRIu16 "-%" PRIu16 ",%" PRIu16
|
||||
") and have (%" PRIu16 ",%" PRIu16 "-%" PRIu16 ",%" PRIu16 ")\n",
|
||||
i, src2->left, src2->top, src2->right, src2->bottom, src1->left,
|
||||
src1->top, src1->right, src1->bottom);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static int test_basic(void)
|
||||
{
|
||||
REGION16 region = WINPR_C_ARRAY_INIT;
|
||||
int retCode = -1;
|
||||
const RECTANGLE_16* rects = nullptr;
|
||||
UINT32 nbRects = 0;
|
||||
/* R1 + R2 ==> disjointed rects */
|
||||
RECTANGLE_16 r1 = { 0, 101, 200, 201 };
|
||||
RECTANGLE_16 r2 = { 150, 301, 250, 401 };
|
||||
RECTANGLE_16 r1_r2[] = { { 0, 101, 200, 201 }, { 150, 301, 250, 401 } };
|
||||
/* r1 */
|
||||
region16_init(®ion);
|
||||
|
||||
if (!region16_union_rect(®ion, ®ion, &r1))
|
||||
goto out;
|
||||
|
||||
rects = region16_rects(®ion, &nbRects);
|
||||
|
||||
if (!rects || nbRects != 1 || memcmp(rects, &r1, sizeof(RECTANGLE_16)) != 0)
|
||||
goto out;
|
||||
|
||||
/* r1 + r2 */
|
||||
if (!region16_union_rect(®ion, ®ion, &r2))
|
||||
goto out;
|
||||
|
||||
rects = region16_rects(®ion, &nbRects);
|
||||
|
||||
if (!rects || nbRects != 2 ||
|
||||
!compareRectangles(rects, r1_r2, WINPR_ASSERTING_INT_CAST(int, nbRects)))
|
||||
goto out;
|
||||
|
||||
/* clear region */
|
||||
region16_clear(®ion);
|
||||
region16_rects(®ion, &nbRects);
|
||||
|
||||
if (nbRects)
|
||||
goto out;
|
||||
|
||||
retCode = 0;
|
||||
out:
|
||||
region16_uninit(®ion);
|
||||
return retCode;
|
||||
}
|
||||
|
||||
static int test_r1_r3(void)
|
||||
{
|
||||
REGION16 region;
|
||||
int retCode = -1;
|
||||
const RECTANGLE_16* rects = nullptr;
|
||||
UINT32 nbRects = 0;
|
||||
RECTANGLE_16 r1 = { 0, 101, 200, 201 };
|
||||
RECTANGLE_16 r3 = { 150, 151, 250, 251 };
|
||||
RECTANGLE_16 r1_r3[] = { { 0, 101, 200, 151 }, { 0, 151, 250, 201 }, { 150, 201, 250, 251 } };
|
||||
region16_init(®ion);
|
||||
/*
|
||||
* +===============================================================
|
||||
* |
|
||||
* |+-----+ +-----+
|
||||
* || r1 | | |
|
||||
* || +-+------+ +-----+--------+
|
||||
* || | r3 | | |
|
||||
* |+---+ | ====> +-----+--------+
|
||||
* | | | | |
|
||||
* | +--------+ +--------+
|
||||
*/
|
||||
|
||||
/* R1 + R3 */
|
||||
if (!region16_union_rect(®ion, ®ion, &r1))
|
||||
goto out;
|
||||
|
||||
if (!region16_union_rect(®ion, ®ion, &r3))
|
||||
goto out;
|
||||
|
||||
rects = region16_rects(®ion, &nbRects);
|
||||
|
||||
if (!rects || nbRects != 3 ||
|
||||
!compareRectangles(rects, r1_r3, WINPR_ASSERTING_INT_CAST(int, nbRects)))
|
||||
goto out;
|
||||
|
||||
/* R3 + R1 */
|
||||
region16_clear(®ion);
|
||||
|
||||
if (!region16_union_rect(®ion, ®ion, &r3))
|
||||
goto out;
|
||||
|
||||
if (!region16_union_rect(®ion, ®ion, &r1))
|
||||
goto out;
|
||||
|
||||
rects = region16_rects(®ion, &nbRects);
|
||||
|
||||
if (!rects || nbRects != 3 ||
|
||||
!compareRectangles(rects, r1_r3, WINPR_ASSERTING_INT_CAST(int, nbRects)))
|
||||
goto out;
|
||||
|
||||
retCode = 0;
|
||||
out:
|
||||
region16_uninit(®ion);
|
||||
return retCode;
|
||||
}
|
||||
|
||||
static int test_r9_r10(void)
|
||||
{
|
||||
REGION16 region;
|
||||
int retCode = -1;
|
||||
const RECTANGLE_16* rects = nullptr;
|
||||
UINT32 nbRects = 0;
|
||||
/*
|
||||
* +===============================================================
|
||||
* |
|
||||
* | +---+ +---+
|
||||
* |+--|r10|-+ +--+---+-+
|
||||
* ||r9| | | | |
|
||||
* || | | | | |
|
||||
* || | | | =====> | |
|
||||
* || | | | | |
|
||||
* || | | | | |
|
||||
* |+--| |-+ +--+---+-+
|
||||
* | +---+ +---+
|
||||
*/
|
||||
RECTANGLE_16 r9 = { 0, 100, 400, 200 };
|
||||
RECTANGLE_16 r10 = { 200, 0, 300, 300 };
|
||||
RECTANGLE_16 r9_r10[] = {
|
||||
{ 200, 0, 300, 100 },
|
||||
{ 0, 100, 400, 200 },
|
||||
{ 200, 200, 300, 300 },
|
||||
};
|
||||
region16_init(®ion);
|
||||
|
||||
if (!region16_union_rect(®ion, ®ion, &r9))
|
||||
goto out;
|
||||
|
||||
if (!region16_union_rect(®ion, ®ion, &r10))
|
||||
goto out;
|
||||
|
||||
rects = region16_rects(®ion, &nbRects);
|
||||
|
||||
if (!rects || nbRects != 3 ||
|
||||
!compareRectangles(rects, r9_r10, WINPR_ASSERTING_INT_CAST(int, nbRects)))
|
||||
goto out;
|
||||
|
||||
retCode = 0;
|
||||
out:
|
||||
region16_uninit(®ion);
|
||||
return retCode;
|
||||
}
|
||||
|
||||
static int test_r1_r5(void)
|
||||
{
|
||||
REGION16 region;
|
||||
int retCode = -1;
|
||||
const RECTANGLE_16* rects = nullptr;
|
||||
UINT32 nbRects = 0;
|
||||
RECTANGLE_16 r1 = { 0, 101, 200, 201 };
|
||||
RECTANGLE_16 r5 = { 150, 121, 300, 131 };
|
||||
RECTANGLE_16 r1_r5[] = { { 0, 101, 200, 121 }, { 0, 121, 300, 131 }, { 0, 131, 200, 201 } };
|
||||
region16_init(®ion);
|
||||
|
||||
/*
|
||||
* +===============================================================
|
||||
* |
|
||||
* |+--------+ +--------+
|
||||
* || r1 | | |
|
||||
* || +--+----+ +--------+----+
|
||||
* || | r5 | =====> | |
|
||||
* || +-------+ +--------+----+
|
||||
* || | | |
|
||||
* |+--------+ +--------+
|
||||
* |
|
||||
*
|
||||
*/
|
||||
if (!region16_union_rect(®ion, ®ion, &r1))
|
||||
goto out;
|
||||
|
||||
if (!region16_union_rect(®ion, ®ion, &r5))
|
||||
goto out;
|
||||
|
||||
rects = region16_rects(®ion, &nbRects);
|
||||
|
||||
if (!rects || nbRects != 3 ||
|
||||
!compareRectangles(rects, r1_r5, WINPR_ASSERTING_INT_CAST(int, nbRects)))
|
||||
goto out;
|
||||
|
||||
retCode = 0;
|
||||
out:
|
||||
region16_uninit(®ion);
|
||||
return retCode;
|
||||
}
|
||||
|
||||
static int test_r1_r6(void)
|
||||
{
|
||||
REGION16 region = WINPR_C_ARRAY_INIT;
|
||||
int retCode = -1;
|
||||
const RECTANGLE_16* rects = nullptr;
|
||||
UINT32 nbRects = 0;
|
||||
RECTANGLE_16 r1 = { 0, 101, 200, 201 };
|
||||
RECTANGLE_16 r6 = { 150, 121, 170, 131 };
|
||||
region16_init(®ion);
|
||||
/*
|
||||
* +===============================================================
|
||||
* |
|
||||
* |+--------+ +--------+
|
||||
* || r1 | | |
|
||||
* || +--+ | | |
|
||||
* || |r6| | =====> | |
|
||||
* || +--+ | | |
|
||||
* || | | |
|
||||
* |+--------+ +--------+
|
||||
* |
|
||||
*/
|
||||
region16_clear(®ion);
|
||||
|
||||
if (!region16_union_rect(®ion, ®ion, &r1))
|
||||
goto out;
|
||||
|
||||
if (!region16_union_rect(®ion, ®ion, &r6))
|
||||
goto out;
|
||||
|
||||
rects = region16_rects(®ion, &nbRects);
|
||||
|
||||
if (!rects || nbRects != 1 ||
|
||||
!compareRectangles(rects, &r1, WINPR_ASSERTING_INT_CAST(int, nbRects)))
|
||||
goto out;
|
||||
|
||||
retCode = 0;
|
||||
out:
|
||||
region16_uninit(®ion);
|
||||
return retCode;
|
||||
}
|
||||
|
||||
static int test_r1_r2_r4(void)
|
||||
{
|
||||
REGION16 region;
|
||||
int retCode = -1;
|
||||
const RECTANGLE_16* rects = nullptr;
|
||||
UINT32 nbRects = 0;
|
||||
RECTANGLE_16 r1 = { 0, 101, 200, 201 };
|
||||
RECTANGLE_16 r2 = { 150, 301, 250, 401 };
|
||||
RECTANGLE_16 r4 = { 150, 251, 250, 301 };
|
||||
RECTANGLE_16 r1_r2_r4[] = { { 0, 101, 200, 201 }, { 150, 251, 250, 401 } };
|
||||
/*
|
||||
* +===============================================================
|
||||
* |
|
||||
* |+-----+ +-----+
|
||||
* || r1 | | |
|
||||
* || | | |
|
||||
* || | | |
|
||||
* |+-----+ ====> +-----+
|
||||
* |
|
||||
* | +--------+ +--------+
|
||||
* | | r4 | | |
|
||||
* | +--------+ | |
|
||||
* | | r2 | | |
|
||||
* | | | | |
|
||||
* | +--------+ +--------+
|
||||
*
|
||||
*/
|
||||
region16_init(®ion);
|
||||
|
||||
if (!region16_union_rect(®ion, ®ion, &r1))
|
||||
goto out;
|
||||
|
||||
if (!region16_union_rect(®ion, ®ion, &r2))
|
||||
goto out;
|
||||
|
||||
if (!region16_union_rect(®ion, ®ion, &r4))
|
||||
goto out;
|
||||
|
||||
rects = region16_rects(®ion, &nbRects);
|
||||
|
||||
if (!rects || nbRects != 2 ||
|
||||
!compareRectangles(rects, r1_r2_r4, WINPR_ASSERTING_INT_CAST(int, nbRects)))
|
||||
goto out;
|
||||
|
||||
retCode = 0;
|
||||
out:
|
||||
region16_uninit(®ion);
|
||||
return retCode;
|
||||
}
|
||||
|
||||
static int test_r1_r7_r8(void)
|
||||
{
|
||||
REGION16 region;
|
||||
int retCode = -1;
|
||||
const RECTANGLE_16* rects = nullptr;
|
||||
UINT32 nbRects = 0;
|
||||
RECTANGLE_16 r1 = { 0, 101, 200, 201 };
|
||||
RECTANGLE_16 r7 = { 300, 101, 500, 201 };
|
||||
RECTANGLE_16 r8 = { 150, 121, 400, 131 };
|
||||
RECTANGLE_16 r1_r7_r8[] = {
|
||||
{ 0, 101, 200, 121 }, { 300, 101, 500, 121 }, { 0, 121, 500, 131 },
|
||||
{ 0, 131, 200, 201 }, { 300, 131, 500, 201 },
|
||||
};
|
||||
/*
|
||||
* +===============================================================
|
||||
* |
|
||||
* |+--------+ +--------+ +--------+ +--------+
|
||||
* || r1 | | r7 | | | | |
|
||||
* || +------------+ | +--------+---+--------+
|
||||
* || | r8 | | =====> | |
|
||||
* || +------------+ | +--------+---+--------+
|
||||
* || | | | | | | |
|
||||
* |+--------+ +--------+ +--------+ +--------+
|
||||
* |
|
||||
*/
|
||||
region16_init(®ion);
|
||||
|
||||
if (!region16_union_rect(®ion, ®ion, &r1))
|
||||
goto out;
|
||||
|
||||
if (!region16_union_rect(®ion, ®ion, &r7))
|
||||
goto out;
|
||||
|
||||
if (!region16_union_rect(®ion, ®ion, &r8))
|
||||
goto out;
|
||||
|
||||
rects = region16_rects(®ion, &nbRects);
|
||||
|
||||
if (!rects || nbRects != 5 ||
|
||||
!compareRectangles(rects, r1_r7_r8, WINPR_ASSERTING_INT_CAST(int, nbRects)))
|
||||
goto out;
|
||||
|
||||
region16_clear(®ion);
|
||||
|
||||
if (!region16_union_rect(®ion, ®ion, &r1))
|
||||
goto out;
|
||||
|
||||
if (!region16_union_rect(®ion, ®ion, &r8))
|
||||
goto out;
|
||||
|
||||
if (!region16_union_rect(®ion, ®ion, &r7))
|
||||
goto out;
|
||||
|
||||
rects = region16_rects(®ion, &nbRects);
|
||||
|
||||
if (!rects || nbRects != 5 ||
|
||||
!compareRectangles(rects, r1_r7_r8, WINPR_ASSERTING_INT_CAST(int, nbRects)))
|
||||
goto out;
|
||||
|
||||
region16_clear(®ion);
|
||||
|
||||
if (!region16_union_rect(®ion, ®ion, &r8))
|
||||
goto out;
|
||||
|
||||
if (!region16_union_rect(®ion, ®ion, &r7))
|
||||
goto out;
|
||||
|
||||
if (!region16_union_rect(®ion, ®ion, &r1))
|
||||
goto out;
|
||||
|
||||
rects = region16_rects(®ion, &nbRects);
|
||||
|
||||
if (!rects || nbRects != 5 ||
|
||||
!compareRectangles(rects, r1_r7_r8, WINPR_ASSERTING_INT_CAST(int, nbRects)))
|
||||
goto out;
|
||||
|
||||
retCode = 0;
|
||||
out:
|
||||
region16_uninit(®ion);
|
||||
return retCode;
|
||||
}
|
||||
|
||||
static int test_r1_r2_r3_r4(void)
|
||||
{
|
||||
REGION16 region;
|
||||
int retCode = -1;
|
||||
const RECTANGLE_16* rects = nullptr;
|
||||
UINT32 nbRects = 0;
|
||||
RECTANGLE_16 r1 = { 0, 101, 200, 201 };
|
||||
RECTANGLE_16 r2 = { 150, 301, 250, 401 };
|
||||
RECTANGLE_16 r3 = { 150, 151, 250, 251 };
|
||||
RECTANGLE_16 r4 = { 150, 251, 250, 301 };
|
||||
RECTANGLE_16 r1_r2_r3[] = {
|
||||
{ 0, 101, 200, 151 }, { 0, 151, 250, 201 }, { 150, 201, 250, 251 }, { 150, 301, 250, 401 }
|
||||
};
|
||||
RECTANGLE_16 r1_r2_r3_r4[] = { { 0, 101, 200, 151 },
|
||||
{ 0, 151, 250, 201 },
|
||||
{ 150, 201, 250, 401 } };
|
||||
region16_init(®ion);
|
||||
|
||||
/*
|
||||
* +===============================================================
|
||||
* |
|
||||
* |+-----+ +-----+
|
||||
* || r1 | | |
|
||||
* || +-+------+ +-----+--------+
|
||||
* || | r3 | | |
|
||||
* |+---+ | ====> +-----+--------+
|
||||
* | | | | |
|
||||
* | +--------+ +--------+
|
||||
* | +--------+ +--------+
|
||||
* | | r2 | | |
|
||||
* | | | | |
|
||||
* | +--------+ +--------+
|
||||
*/
|
||||
if (!region16_union_rect(®ion, ®ion, &r1))
|
||||
goto out;
|
||||
|
||||
if (!region16_union_rect(®ion, ®ion, &r2))
|
||||
goto out;
|
||||
|
||||
if (!region16_union_rect(®ion, ®ion, &r3))
|
||||
goto out;
|
||||
|
||||
rects = region16_rects(®ion, &nbRects);
|
||||
|
||||
if (!rects || nbRects != 4 || !compareRectangles(rects, r1_r2_r3, 4))
|
||||
goto out;
|
||||
|
||||
/*
|
||||
* +===============================================================
|
||||
* |
|
||||
* |+-----+ +-----+
|
||||
* || | | |
|
||||
* |+-----+--------+ +-----+--------+
|
||||
* || | ==> | |
|
||||
* |+-----+--------+ +-----+--------+
|
||||
* | | | | |
|
||||
* | +--------+ | |
|
||||
* | | + r4 | | |
|
||||
* | +--------+ | |
|
||||
* | | | | |
|
||||
* | | | | |
|
||||
* | +--------+ +--------+
|
||||
*/
|
||||
if (!region16_union_rect(®ion, ®ion, &r4))
|
||||
goto out;
|
||||
|
||||
rects = region16_rects(®ion, &nbRects);
|
||||
|
||||
if (!rects || nbRects != 3 || !compareRectangles(rects, r1_r2_r3_r4, 3))
|
||||
goto out;
|
||||
|
||||
retCode = 0;
|
||||
out:
|
||||
region16_uninit(®ion);
|
||||
return retCode;
|
||||
}
|
||||
|
||||
static int test_from_weston(void)
|
||||
{
|
||||
/*
|
||||
* 0: 0,0 -> 640,32 (w=640 h=32)
|
||||
* 1: 236,169 -> 268,201 (w=32 h=32)
|
||||
* 2: 246,258 -> 278,290 (w=32 h=32)
|
||||
*/
|
||||
REGION16 region;
|
||||
int retCode = -1;
|
||||
const RECTANGLE_16* rects = nullptr;
|
||||
UINT32 nbRects = 0;
|
||||
RECTANGLE_16 r1 = { 0, 0, 640, 32 };
|
||||
RECTANGLE_16 r2 = { 236, 169, 268, 201 };
|
||||
RECTANGLE_16 r3 = { 246, 258, 278, 290 };
|
||||
RECTANGLE_16 r1_r2_r3[] = { { 0, 0, 640, 32 }, { 236, 169, 268, 201 }, { 246, 258, 278, 290 } };
|
||||
region16_init(®ion);
|
||||
|
||||
/*
|
||||
* +===============================================================
|
||||
* |+-------------------------------------------------------------+
|
||||
* || r1 |
|
||||
* |+-------------------------------------------------------------+
|
||||
* |
|
||||
* | +---------------+
|
||||
* | | r2 |
|
||||
* | +---------------+
|
||||
* |
|
||||
* | +---------------+
|
||||
* | | r3 |
|
||||
* | +---------------+
|
||||
* |
|
||||
*/
|
||||
if (!region16_union_rect(®ion, ®ion, &r1))
|
||||
goto out;
|
||||
|
||||
if (!region16_union_rect(®ion, ®ion, &r2))
|
||||
goto out;
|
||||
|
||||
if (!region16_union_rect(®ion, ®ion, &r3))
|
||||
goto out;
|
||||
|
||||
rects = region16_rects(®ion, &nbRects);
|
||||
|
||||
if (!rects || nbRects != 3 || !compareRectangles(rects, r1_r2_r3, 3))
|
||||
goto out;
|
||||
|
||||
retCode = 0;
|
||||
out:
|
||||
region16_uninit(®ion);
|
||||
return retCode;
|
||||
}
|
||||
|
||||
static int test_r1_inter_r3(void)
|
||||
{
|
||||
REGION16 region;
|
||||
REGION16 intersection;
|
||||
int retCode = -1;
|
||||
const RECTANGLE_16* rects = nullptr;
|
||||
UINT32 nbRects = 0;
|
||||
RECTANGLE_16 r1 = { 0, 101, 200, 201 };
|
||||
RECTANGLE_16 r3 = { 150, 151, 250, 251 };
|
||||
RECTANGLE_16 r1_inter_r3[] = {
|
||||
{ 150, 151, 200, 201 },
|
||||
};
|
||||
region16_init(®ion);
|
||||
region16_init(&intersection);
|
||||
|
||||
/*
|
||||
* +===============================================================
|
||||
* |
|
||||
* |+-----+
|
||||
* || r1 |
|
||||
* || +-+------+ +-+
|
||||
* || | r3 | r1&r3 | |
|
||||
* |+---+ | ====> +-+
|
||||
* | | |
|
||||
* | +--------+
|
||||
*/
|
||||
if (!region16_union_rect(®ion, ®ion, &r1))
|
||||
goto out;
|
||||
|
||||
if (!region16_intersects_rect(®ion, &r3))
|
||||
goto out;
|
||||
|
||||
if (!region16_intersect_rect(&intersection, ®ion, &r3))
|
||||
goto out;
|
||||
|
||||
rects = region16_rects(&intersection, &nbRects);
|
||||
|
||||
if (!rects || nbRects != 1 ||
|
||||
!compareRectangles(rects, r1_inter_r3, WINPR_ASSERTING_INT_CAST(int, nbRects)))
|
||||
goto out;
|
||||
|
||||
retCode = 0;
|
||||
out:
|
||||
region16_uninit(®ion);
|
||||
region16_uninit(&intersection);
|
||||
return retCode;
|
||||
}
|
||||
|
||||
static int test_r1_r3_inter_r11(void)
|
||||
{
|
||||
REGION16 region;
|
||||
REGION16 intersection;
|
||||
int retCode = -1;
|
||||
const RECTANGLE_16* rects = nullptr;
|
||||
UINT32 nbRects = 0;
|
||||
RECTANGLE_16 r1 = { 0, 101, 200, 201 };
|
||||
RECTANGLE_16 r3 = { 150, 151, 250, 251 };
|
||||
RECTANGLE_16 r11 = { 170, 151, 600, 301 };
|
||||
RECTANGLE_16 r1_r3_inter_r11[] = {
|
||||
{ 170, 151, 250, 251 },
|
||||
};
|
||||
region16_init(®ion);
|
||||
region16_init(&intersection);
|
||||
|
||||
/*
|
||||
* +===============================================================
|
||||
* |
|
||||
* |+-----+
|
||||
* || |
|
||||
* || +------+
|
||||
* || r1+r3 | (r1+r3) & r11
|
||||
* || +----------------+ +--------+
|
||||
* |+---+ | | | ====> | |
|
||||
* | | | | | | |
|
||||
* | | | | | | |
|
||||
* | +-|------+ | +--------+
|
||||
* | | r11 |
|
||||
* | +----------------+
|
||||
*
|
||||
*
|
||||
* R1+R3 is made of 3 bands, R11 overlap the second and the third band. The
|
||||
* intersection is made of two band that must be reassembled to give only
|
||||
* one
|
||||
*/
|
||||
if (!region16_union_rect(®ion, ®ion, &r1))
|
||||
goto out;
|
||||
|
||||
if (!region16_union_rect(®ion, ®ion, &r3))
|
||||
goto out;
|
||||
|
||||
if (!region16_intersects_rect(®ion, &r11))
|
||||
goto out;
|
||||
|
||||
if (!region16_intersect_rect(&intersection, ®ion, &r11))
|
||||
goto out;
|
||||
|
||||
rects = region16_rects(&intersection, &nbRects);
|
||||
|
||||
if (!rects || nbRects != 1 ||
|
||||
!compareRectangles(rects, r1_r3_inter_r11, WINPR_ASSERTING_INT_CAST(int, nbRects)))
|
||||
goto out;
|
||||
|
||||
retCode = 0;
|
||||
out:
|
||||
region16_uninit(&intersection);
|
||||
region16_uninit(®ion);
|
||||
return retCode;
|
||||
}
|
||||
|
||||
static int test_norbert_case(void)
|
||||
{
|
||||
REGION16 region;
|
||||
REGION16 intersection;
|
||||
int retCode = -1;
|
||||
const RECTANGLE_16* rects = nullptr;
|
||||
UINT32 nbRects = 0;
|
||||
RECTANGLE_16 inRectangles[5] = { { 1680, 0, 1920, 242 },
|
||||
{ 294, 242, 971, 776 },
|
||||
{ 1680, 242, 1920, 776 },
|
||||
{ 1680, 776, 1920, 1036 },
|
||||
{ 2, 1040, 53, 1078 } };
|
||||
RECTANGLE_16 screenRect = { 0, 0, 1920, 1080 };
|
||||
RECTANGLE_16 expected_inter_extents = { 2, 0, 1920, 1078 };
|
||||
region16_init(®ion);
|
||||
region16_init(&intersection);
|
||||
|
||||
/*
|
||||
* Consider following as a screen with resolution 1920*1080
|
||||
* | | | | | | |
|
||||
* | |2 |53 |294 |971 |1680 |
|
||||
* | | | | | | |
|
||||
* 0 +=+======================================+======+
|
||||
* | | | |
|
||||
* | | R[0]|
|
||||
* 242 | +-----------+ +------+
|
||||
* | | | | | |
|
||||
* | | | | |
|
||||
* | | R[1]| | R[2]|
|
||||
* 776 | | +-----------+ +------+
|
||||
* | | |
|
||||
* | | R[3]|
|
||||
* 1036 | | +------+
|
||||
* 1040 | +----+
|
||||
* | |R[4]| Union of R[0-4]|
|
||||
* 1078 | +----+ - - - - - - - -+
|
||||
* 1080 |
|
||||
*
|
||||
*
|
||||
* The result is union of R[0] - R[4].
|
||||
* After intersected with the full screen rect, the
|
||||
* result should keep the same.
|
||||
*/
|
||||
for (int i = 0; i < 5; i++)
|
||||
{
|
||||
if (!region16_union_rect(®ion, ®ion, &inRectangles[i]))
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!compareRectangles(region16_extents(®ion), &expected_inter_extents, 1))
|
||||
goto out;
|
||||
|
||||
if (!region16_intersect_rect(&intersection, ®ion, &screenRect))
|
||||
goto out;
|
||||
|
||||
rects = region16_rects(&intersection, &nbRects);
|
||||
|
||||
if (!rects || nbRects != 5 ||
|
||||
!compareRectangles(rects, inRectangles, WINPR_ASSERTING_INT_CAST(int, nbRects)))
|
||||
goto out;
|
||||
|
||||
if (!compareRectangles(region16_extents(&intersection), &expected_inter_extents, 1))
|
||||
goto out;
|
||||
|
||||
retCode = 0;
|
||||
out:
|
||||
region16_uninit(&intersection);
|
||||
region16_uninit(®ion);
|
||||
return retCode;
|
||||
}
|
||||
|
||||
static int test_norbert2_case(void)
|
||||
{
|
||||
REGION16 region;
|
||||
int retCode = -1;
|
||||
const RECTANGLE_16* rects = nullptr;
|
||||
UINT32 nbRects = 0;
|
||||
RECTANGLE_16 rect1 = { 464, 696, 476, 709 };
|
||||
RECTANGLE_16 rect2 = { 0, 0, 1024, 32 };
|
||||
region16_init(®ion);
|
||||
|
||||
if (!region16_union_rect(®ion, ®ion, &rect1))
|
||||
{
|
||||
(void)fprintf(stderr, "%s: Error 1 - region16_union_rect failed\n", __func__);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!(rects = region16_rects(®ion, &nbRects)))
|
||||
{
|
||||
(void)fprintf(stderr, "%s: Error 2 - region16_rects failed\n", __func__);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (nbRects != 1)
|
||||
{
|
||||
(void)fprintf(stderr, "%s: Error 3 - expected nbRects == 1 but got %" PRIu32 "\n", __func__,
|
||||
nbRects);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!compareRectangles(&rects[0], &rect1, 1))
|
||||
{
|
||||
(void)fprintf(stderr, "%s: Error 4 - compare failed\n", __func__);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!region16_union_rect(®ion, ®ion, &rect2))
|
||||
{
|
||||
(void)fprintf(stderr, "%s: Error 5 - region16_union_rect failed\n", __func__);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!(rects = region16_rects(®ion, &nbRects)))
|
||||
{
|
||||
(void)fprintf(stderr, "%s: Error 6 - region16_rects failed\n", __func__);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (nbRects != 2)
|
||||
{
|
||||
(void)fprintf(stderr, "%s: Error 7 - expected nbRects == 2 but got %" PRIu32 "\n", __func__,
|
||||
nbRects);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!compareRectangles(&rects[0], &rect2, 1))
|
||||
{
|
||||
(void)fprintf(stderr, "%s: Error 8 - compare failed\n", __func__);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!compareRectangles(&rects[1], &rect1, 1))
|
||||
{
|
||||
(void)fprintf(stderr, "%s: Error 9 - compare failed\n", __func__);
|
||||
goto out;
|
||||
}
|
||||
|
||||
retCode = 0;
|
||||
out:
|
||||
region16_uninit(®ion);
|
||||
return retCode;
|
||||
}
|
||||
|
||||
static int test_empty_rectangle(void)
|
||||
{
|
||||
REGION16 region;
|
||||
REGION16 intersection;
|
||||
int retCode = -1;
|
||||
RECTANGLE_16 emptyRectangles[3] = { { 0, 0, 0, 0 }, { 10, 10, 10, 11 }, { 10, 10, 11, 10 } };
|
||||
RECTANGLE_16 firstRect = { 0, 0, 100, 100 };
|
||||
RECTANGLE_16 anotherRect = { 100, 100, 200, 200 };
|
||||
RECTANGLE_16 expected_inter_extents = { 0, 0, 0, 0 };
|
||||
region16_init(®ion);
|
||||
region16_init(&intersection);
|
||||
|
||||
/* Check for empty rectangles */
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
if (!rectangle_is_empty(&emptyRectangles[i]))
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Check for non-empty rectangles */
|
||||
if (rectangle_is_empty(&firstRect))
|
||||
goto out;
|
||||
|
||||
/* Intersect 2 non-intersect rectangle, result should be empty */
|
||||
if (!region16_union_rect(®ion, ®ion, &firstRect))
|
||||
goto out;
|
||||
|
||||
if (!region16_intersect_rect(®ion, ®ion, &anotherRect))
|
||||
goto out;
|
||||
|
||||
if (!compareRectangles(region16_extents(®ion), &expected_inter_extents, 1))
|
||||
goto out;
|
||||
|
||||
if (!region16_is_empty(®ion))
|
||||
goto out;
|
||||
|
||||
if (!rectangle_is_empty(region16_extents(&intersection)))
|
||||
goto out;
|
||||
|
||||
retCode = 0;
|
||||
out:
|
||||
region16_uninit(&intersection);
|
||||
region16_uninit(®ion);
|
||||
return retCode;
|
||||
}
|
||||
|
||||
typedef int (*TestFunction)(void);
|
||||
struct UnitaryTest
|
||||
{
|
||||
const char* name;
|
||||
WINPR_ATTR_NODISCARD TestFunction func;
|
||||
};
|
||||
|
||||
static struct UnitaryTest tests[] = { { "Basic trivial tests", test_basic },
|
||||
{ "R1+R3 and R3+R1", test_r1_r3 },
|
||||
{ "R1+R5", test_r1_r5 },
|
||||
{ "R1+R6", test_r1_r6 },
|
||||
{ "R9+R10", test_r9_r10 },
|
||||
{ "R1+R2+R4", test_r1_r2_r4 },
|
||||
{ "R1+R7+R8 in many orders", test_r1_r7_r8 },
|
||||
{ "R1+R2+R3+R4", test_r1_r2_r3_r4 },
|
||||
{ "data from weston", test_from_weston },
|
||||
{ "R1 & R3", test_r1_inter_r3 },
|
||||
{ "(R1+R3)&R11 (band merge)", test_r1_r3_inter_r11 },
|
||||
{ "norbert's case", test_norbert_case },
|
||||
{ "norbert's case 2", test_norbert2_case },
|
||||
{ "empty rectangle case", test_empty_rectangle },
|
||||
|
||||
{ nullptr, nullptr } };
|
||||
|
||||
int TestFreeRDPRegion(int argc, char* argv[])
|
||||
{
|
||||
int testNb = 0;
|
||||
int retCode = -1;
|
||||
WINPR_UNUSED(argc);
|
||||
WINPR_UNUSED(argv);
|
||||
|
||||
for (int i = 0; tests[i].func; i++)
|
||||
{
|
||||
testNb++;
|
||||
(void)fprintf(stderr, "%d: %s\n", testNb, tests[i].name);
|
||||
retCode = tests[i].func();
|
||||
|
||||
if (retCode < 0)
|
||||
break;
|
||||
}
|
||||
|
||||
if (retCode < 0)
|
||||
(void)fprintf(stderr, "failed for test %d\n", testNb);
|
||||
|
||||
return retCode;
|
||||
}
|
||||
Reference in New Issue
Block a user