mutter/src/tests/monitor-test-utils.c
Marco Trevisan (Treviño) 3baf750e42 monitor-test-utils: Add debug friendly statements during tests
Monitor configuration check tests can be very complex and in case of
failures we can't easily catch where a failure happened without entering
in debug mode, something that isn't always an option in CI or external
builders.

So add more debug statements in configuration check functions and use
macros to ensure that we print the caller function and location on more
complex check functions.

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/522>
2021-08-04 14:02:16 +00:00

879 lines
29 KiB
C

/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* Copyright (C) 2017 Red Hat, Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#include "config.h"
#include "tests/monitor-test-utils.h"
#include <float.h>
#include "backends/meta-backend-private.h"
#include "backends/meta-crtc.h"
#include "backends/meta-logical-monitor.h"
#include "backends/meta-monitor-config-manager.h"
#include "backends/meta-monitor-config-store.h"
#include "backends/meta-output.h"
#include "tests/meta-test-utils.h"
#include "meta-backend-test.h"
MetaGpu *
test_get_gpu (void)
{
return META_GPU (meta_backend_get_gpus (meta_get_backend ())->data);
}
void
set_custom_monitor_config (const char *filename)
{
MetaBackend *backend = meta_get_backend ();
MetaMonitorManager *monitor_manager =
meta_backend_get_monitor_manager (backend);
MetaMonitorConfigManager *config_manager = monitor_manager->config_manager;
MetaMonitorConfigStore *config_store;
GError *error = NULL;
const char *path;
g_assert_nonnull (config_manager);
config_store = meta_monitor_config_manager_get_store (config_manager);
path = g_test_get_filename (G_TEST_DIST, "tests", "monitor-configs",
filename, NULL);
if (!meta_monitor_config_store_set_custom (config_store, path, NULL,
&error))
g_error ("Failed to set custom config: %s", error->message);
}
char *
read_file (const char *file_path)
{
g_autoptr (GFile) file = NULL;
g_autoptr (GFileInputStream) input_stream = NULL;
g_autoptr (GFileInfo) file_info = NULL;
goffset file_size;
gsize bytes_read;
g_autofree char *buffer = NULL;
GError *error = NULL;
file = g_file_new_for_path (file_path);
input_stream = g_file_read (file, NULL, &error);
if (!input_stream)
g_error ("Failed to read migrated config file: %s", error->message);
file_info = g_file_input_stream_query_info (input_stream,
G_FILE_ATTRIBUTE_STANDARD_SIZE,
NULL, &error);
if (!file_info)
g_error ("Failed to read file info: %s", error->message);
file_size = g_file_info_get_size (file_info);
buffer = g_malloc0 (file_size + 1);
if (!g_input_stream_read_all (G_INPUT_STREAM (input_stream),
buffer, file_size, &bytes_read, NULL, &error))
g_error ("Failed to read file content: %s", error->message);
g_assert_cmpint ((goffset) bytes_read, ==, file_size);
return g_steal_pointer (&buffer);
}
static MetaOutput *
output_from_winsys_id (MetaBackend *backend,
uint64_t output_id)
{
MetaGpu *gpu = meta_backend_test_get_gpu (META_BACKEND_TEST (backend));
GList *l;
for (l = meta_gpu_get_outputs (gpu); l; l = l->next)
{
MetaOutput *output = l->data;
if (meta_output_get_id (output) == output_id)
return output;
}
return NULL;
}
typedef struct _CheckMonitorModeData
{
MetaBackend *backend;
MetaTestCaseMonitorCrtcMode *expect_crtc_mode_iter;
} CheckMonitorModeData;
static gboolean
check_monitor_mode (MetaMonitor *monitor,
MetaMonitorMode *mode,
MetaMonitorCrtcMode *monitor_crtc_mode,
gpointer user_data,
GError **error)
{
CheckMonitorModeData *data = user_data;
MetaBackend *backend = data->backend;
MetaOutput *output;
MetaCrtcMode *crtc_mode;
int expect_crtc_mode_index;
output = output_from_winsys_id (backend,
data->expect_crtc_mode_iter->output);
g_assert (monitor_crtc_mode->output == output);
expect_crtc_mode_index = data->expect_crtc_mode_iter->crtc_mode;
if (expect_crtc_mode_index == -1)
{
crtc_mode = NULL;
}
else
{
MetaGpu *gpu = meta_output_get_gpu (output);
crtc_mode = g_list_nth_data (meta_gpu_get_modes (gpu),
expect_crtc_mode_index);
}
g_assert (monitor_crtc_mode->crtc_mode == crtc_mode);
if (crtc_mode)
{
const MetaCrtcModeInfo *crtc_mode_info =
meta_crtc_mode_get_info (crtc_mode);
float refresh_rate;
MetaCrtcModeFlag flags;
refresh_rate = meta_monitor_mode_get_refresh_rate (mode);
flags = meta_monitor_mode_get_flags (mode);
g_assert_cmpfloat (refresh_rate, ==, crtc_mode_info->refresh_rate);
g_assert_cmpint (flags, ==, (crtc_mode_info->flags &
HANDLED_CRTC_MODE_FLAGS));
}
data->expect_crtc_mode_iter++;
return TRUE;
}
static gboolean
check_current_monitor_mode (MetaMonitor *monitor,
MetaMonitorMode *mode,
MetaMonitorCrtcMode *monitor_crtc_mode,
gpointer user_data,
GError **error)
{
CheckMonitorModeData *data = user_data;
MetaBackend *backend = data->backend;
MetaOutput *output;
MetaCrtc *crtc;
output = output_from_winsys_id (backend,
data->expect_crtc_mode_iter->output);
crtc = meta_output_get_assigned_crtc (output);
if (data->expect_crtc_mode_iter->crtc_mode == -1)
{
g_assert_null (crtc);
}
else
{
const MetaCrtcConfig *crtc_config;
MetaLogicalMonitor *logical_monitor;
g_assert_nonnull (crtc);
crtc_config = meta_crtc_get_config (crtc);
g_assert_nonnull (crtc_config);
g_assert (monitor_crtc_mode->crtc_mode == crtc_config->mode);
logical_monitor = meta_monitor_get_logical_monitor (monitor);
g_assert_nonnull (logical_monitor);
}
data->expect_crtc_mode_iter++;
return TRUE;
}
static MetaLogicalMonitor *
logical_monitor_from_layout (MetaMonitorManager *monitor_manager,
MetaRectangle *layout)
{
GList *l;
for (l = monitor_manager->logical_monitors; l; l = l->next)
{
MetaLogicalMonitor *logical_monitor = l->data;
if (meta_rectangle_equal (layout, &logical_monitor->rect))
return logical_monitor;
}
return NULL;
}
static void
check_logical_monitor (MetaMonitorManager *monitor_manager,
MonitorTestCaseLogicalMonitor *test_logical_monitor,
GList **all_crtcs)
{
MetaLogicalMonitor *logical_monitor;
MetaOutput *primary_output;
GList *monitors;
GList *l;
int i;
logical_monitor = logical_monitor_from_layout (monitor_manager,
&test_logical_monitor->layout);
g_assert_nonnull (logical_monitor);
g_assert_cmpint (logical_monitor->rect.x,
==,
test_logical_monitor->layout.x);
g_assert_cmpint (logical_monitor->rect.y,
==,
test_logical_monitor->layout.y);
g_assert_cmpint (logical_monitor->rect.width,
==,
test_logical_monitor->layout.width);
g_assert_cmpint (logical_monitor->rect.height,
==,
test_logical_monitor->layout.height);
g_assert_cmpfloat (logical_monitor->scale,
==,
test_logical_monitor->scale);
g_assert_cmpuint (logical_monitor->transform,
==,
test_logical_monitor->transform);
if (logical_monitor == monitor_manager->primary_logical_monitor)
g_assert (meta_logical_monitor_is_primary (logical_monitor));
primary_output = NULL;
monitors = meta_logical_monitor_get_monitors (logical_monitor);
g_assert_cmpint ((int) g_list_length (monitors),
==,
test_logical_monitor->n_monitors);
for (i = 0; i < test_logical_monitor->n_monitors; i++)
{
MetaMonitor *monitor =
g_list_nth (monitor_manager->monitors,
test_logical_monitor->monitors[i])->data;
g_assert_nonnull (g_list_find (monitors, monitor));
}
for (l = monitors; l; l = l->next)
{
MetaMonitor *monitor = l->data;
GList *outputs;
GList *l_output;
outputs = meta_monitor_get_outputs (monitor);
for (l_output = outputs; l_output; l_output = l_output->next)
{
MetaOutput *output = l_output->data;
MetaCrtc *crtc;
g_assert (meta_output_get_monitor (output) == monitor);
if (meta_output_is_primary (output))
{
g_assert_null (primary_output);
primary_output = output;
}
crtc = meta_output_get_assigned_crtc (output);
if (crtc)
{
g_assert (meta_monitor_get_logical_monitor (monitor) ==
logical_monitor);
g_assert (g_list_find ((GList *) meta_crtc_get_outputs (crtc),
output));
*all_crtcs = g_list_remove (*all_crtcs, crtc);
}
else
{
g_assert_null (crtc);
}
g_assert_cmpint (logical_monitor->is_presentation,
==,
meta_output_is_presentation (output));
}
}
if (logical_monitor == monitor_manager->primary_logical_monitor)
g_assert_nonnull (primary_output);
}
void
check_monitor_configuration (MonitorTestCaseExpect *expect)
{
MetaBackend *backend = meta_get_backend ();
MetaRenderer *renderer = meta_backend_get_renderer (backend);
MetaMonitorManager *monitor_manager =
meta_backend_get_monitor_manager (backend);
MetaMonitorManagerTest *monitor_manager_test =
META_MONITOR_MANAGER_TEST (monitor_manager);
MetaGpu *gpu = meta_backend_test_get_gpu (META_BACKEND_TEST (backend));
int tiled_monitor_count;
GList *monitors;
GList *crtcs;
int n_logical_monitors;
GList *all_crtcs;
GList *l;
int i;
g_assert_cmpint (monitor_manager->screen_width,
==,
expect->screen_width);
g_assert_cmpint (monitor_manager->screen_height,
==,
expect->screen_height);
g_assert_cmpint ((int) g_list_length (meta_gpu_get_outputs (gpu)),
==,
expect->n_outputs);
g_assert_cmpint ((int) g_list_length (meta_gpu_get_crtcs (gpu)),
==,
expect->n_crtcs);
tiled_monitor_count =
meta_monitor_manager_test_get_tiled_monitor_count (monitor_manager_test);
g_assert_cmpint (tiled_monitor_count,
==,
expect->n_tiled_monitors);
monitors = meta_monitor_manager_get_monitors (monitor_manager);
g_assert_cmpint ((int) g_list_length (monitors),
==,
expect->n_monitors);
for (l = monitors, i = 0; l; l = l->next, i++)
{
MetaMonitor *monitor = l->data;
MetaOutput *main_output;
const MetaOutputInfo *main_output_info;
GList *outputs;
GList *l_output;
int j;
int width_mm, height_mm;
GList *modes;
GList *l_mode;
MetaMonitorMode *current_mode;
int expected_current_mode_index;
MetaMonitorMode *expected_current_mode;
outputs = meta_monitor_get_outputs (monitor);
g_debug ("Checking monitor %d", i);
g_assert_cmpint ((int) g_list_length (outputs),
==,
expect->monitors[i].n_outputs);
for (l_output = outputs, j = 0; l_output; l_output = l_output->next, j++)
{
MetaOutput *output = l_output->data;
uint64_t winsys_id = expect->monitors[i].outputs[j];
g_assert (output == output_from_winsys_id (backend, winsys_id));
g_assert_cmpint (expect->monitors[i].is_underscanning,
==,
meta_output_is_underscanning (output));
}
meta_monitor_get_physical_dimensions (monitor, &width_mm, &height_mm);
g_assert_cmpint (width_mm,
==,
expect->monitors[i].width_mm);
g_assert_cmpint (height_mm,
==,
expect->monitors[i].height_mm);
main_output = meta_monitor_get_main_output (monitor);
main_output_info = meta_output_get_info (main_output);
g_assert_cmpstr (meta_monitor_get_connector (monitor), ==,
main_output_info->name);
g_assert_cmpstr (meta_monitor_get_vendor (monitor), ==,
main_output_info->vendor);
g_assert_cmpstr (meta_monitor_get_product (monitor), ==,
main_output_info->product);
g_assert_cmpstr (meta_monitor_get_serial (monitor), ==,
main_output_info->serial);
g_assert_cmpint (meta_monitor_get_connector_type (monitor), ==,
main_output_info->connector_type);
modes = meta_monitor_get_modes (monitor);
g_assert_cmpint (g_list_length (modes),
==,
expect->monitors[i].n_modes);
for (l_mode = modes, j = 0; l_mode; l_mode = l_mode->next, j++)
{
MetaMonitorMode *mode = l_mode->data;
int width;
int height;
float refresh_rate;
MetaCrtcModeFlag flags;
CheckMonitorModeData data;
meta_monitor_mode_get_resolution (mode, &width, &height);
refresh_rate = meta_monitor_mode_get_refresh_rate (mode);
flags = meta_monitor_mode_get_flags (mode);
g_debug ("Checking mode %dx%d @ %f", width, height, refresh_rate);
g_assert_cmpint (width,
==,
expect->monitors[i].modes[j].width);
g_assert_cmpint (height,
==,
expect->monitors[i].modes[j].height);
g_assert_cmpfloat (refresh_rate,
==,
expect->monitors[i].modes[j].refresh_rate);
g_assert_cmpint (flags,
==,
expect->monitors[i].modes[j].flags);
data = (CheckMonitorModeData) {
.backend = backend,
.expect_crtc_mode_iter =
expect->monitors[i].modes[j].crtc_modes
};
meta_monitor_mode_foreach_output (monitor, mode,
check_monitor_mode,
&data,
NULL);
}
current_mode = meta_monitor_get_current_mode (monitor);
expected_current_mode_index = expect->monitors[i].current_mode;
if (expected_current_mode_index == -1)
expected_current_mode = NULL;
else
expected_current_mode = g_list_nth (modes,
expected_current_mode_index)->data;
g_assert (current_mode == expected_current_mode);
if (current_mode)
g_assert (meta_monitor_is_active (monitor));
else
g_assert (!meta_monitor_is_active (monitor));
if (current_mode)
{
CheckMonitorModeData data;
data = (CheckMonitorModeData) {
.backend = backend,
.expect_crtc_mode_iter =
expect->monitors[i].modes[expected_current_mode_index].crtc_modes
};
meta_monitor_mode_foreach_output (monitor, expected_current_mode,
check_current_monitor_mode,
&data,
NULL);
}
meta_monitor_derive_current_mode (monitor);
g_assert (current_mode == meta_monitor_get_current_mode (monitor));
}
n_logical_monitors =
meta_monitor_manager_get_num_logical_monitors (monitor_manager);
g_assert_cmpint (n_logical_monitors,
==,
expect->n_logical_monitors);
/*
* Check that we have a primary logical monitor (except for headless),
* and that the main output of the first monitor is the only output
* that is marked as primary (further below). Note: outputs being primary or
* not only matters on X11.
*/
if (expect->primary_logical_monitor == -1)
{
g_assert_null (monitor_manager->primary_logical_monitor);
g_assert_null (monitor_manager->logical_monitors);
}
else
{
MonitorTestCaseLogicalMonitor *test_logical_monitor =
&expect->logical_monitors[expect->primary_logical_monitor];
MetaLogicalMonitor *logical_monitor;
logical_monitor =
logical_monitor_from_layout (monitor_manager,
&test_logical_monitor->layout);
g_assert (logical_monitor == monitor_manager->primary_logical_monitor);
}
all_crtcs = NULL;
for (l = meta_backend_get_gpus (backend); l; l = l->next)
{
MetaGpu *gpu = l->data;
all_crtcs = g_list_concat (all_crtcs,
g_list_copy (meta_gpu_get_crtcs (gpu)));
}
for (i = 0; i < expect->n_logical_monitors; i++)
{
MonitorTestCaseLogicalMonitor *test_logical_monitor =
&expect->logical_monitors[i];
check_logical_monitor (monitor_manager, test_logical_monitor, &all_crtcs);
}
g_assert_cmpint (n_logical_monitors, ==, i);
for (l = all_crtcs; l; l = l->next)
{
MetaCrtc *crtc = l->data;
g_assert_null (meta_crtc_get_outputs (crtc));
}
g_list_free (all_crtcs);
crtcs = meta_gpu_get_crtcs (gpu);
for (l = crtcs, i = 0; l; l = l->next, i++)
{
MetaCrtc *crtc = l->data;
const MetaCrtcConfig *crtc_config = meta_crtc_get_config (crtc);
g_debug ("Checking CRTC %d", i);
if (expect->crtcs[i].current_mode == -1)
{
g_assert_null (meta_crtc_get_outputs (crtc));
g_assert_null (crtc_config);
}
else
{
MetaCrtcMode *expected_current_mode;
const GList *outputs = meta_crtc_get_outputs (crtc);
const GList *l_output;
MetaRendererView *view;
cairo_rectangle_int_t view_layout;
for (l_output = outputs;
l_output;
l_output = l_output->next)
{
MetaOutput *output = l_output->data;
g_debug ("Checking CRTC Output %d",
g_list_index ((GList *) outputs, output));
g_assert (meta_output_get_assigned_crtc (output) == crtc);
g_assert_null (g_list_find (l_output->next, output));
}
g_assert_nonnull (crtc_config);
expected_current_mode =
g_list_nth_data (meta_gpu_get_modes (gpu),
expect->crtcs[i].current_mode);
g_assert (crtc_config->mode == expected_current_mode);
g_assert_cmpuint (crtc_config->transform,
==,
expect->crtcs[i].transform);
g_assert_cmpfloat_with_epsilon (crtc_config->layout.origin.x,
expect->crtcs[i].x,
FLT_EPSILON);
g_assert_cmpfloat_with_epsilon (crtc_config->layout.origin.y,
expect->crtcs[i].y,
FLT_EPSILON);
view = meta_renderer_get_view_for_crtc (renderer, crtc);
g_assert_nonnull (view);
clutter_stage_view_get_layout (CLUTTER_STAGE_VIEW (view),
&view_layout);
g_assert_cmpfloat_with_epsilon (crtc_config->layout.origin.x,
view_layout.x,
FLT_EPSILON);
g_assert_cmpfloat_with_epsilon (crtc_config->layout.origin.y,
view_layout.y,
FLT_EPSILON);
g_assert_cmpfloat_with_epsilon (crtc_config->layout.size.width,
view_layout.width,
FLT_EPSILON);
g_assert_cmpfloat_with_epsilon (crtc_config->layout.size.height,
view_layout.height,
FLT_EPSILON);
}
}
}
MetaMonitorTestSetup *
create_monitor_test_setup (MonitorTestCaseSetup *setup,
MonitorTestFlag flags)
{
MetaMonitorTestSetup *test_setup;
int i;
int n_laptop_panels = 0;
int n_normal_panels = 0;
test_setup = g_new0 (MetaMonitorTestSetup, 1);
test_setup->modes = NULL;
for (i = 0; i < setup->n_modes; i++)
{
g_autoptr (MetaCrtcModeInfo) crtc_mode_info = NULL;
MetaCrtcMode *mode;
crtc_mode_info = meta_crtc_mode_info_new ();
crtc_mode_info->width = setup->modes[i].width;
crtc_mode_info->height = setup->modes[i].height;
crtc_mode_info->refresh_rate = setup->modes[i].refresh_rate;
crtc_mode_info->flags = setup->modes[i].flags;
mode = g_object_new (META_TYPE_CRTC_MODE,
"id", (uint64_t) i,
"info", crtc_mode_info,
NULL);
test_setup->modes = g_list_append (test_setup->modes, mode);
}
test_setup->crtcs = NULL;
for (i = 0; i < setup->n_crtcs; i++)
{
MetaCrtc *crtc;
crtc = g_object_new (META_TYPE_CRTC_TEST,
"id", (uint64_t) i + 1,
"gpu", test_get_gpu (),
NULL);
test_setup->crtcs = g_list_append (test_setup->crtcs, crtc);
}
test_setup->outputs = NULL;
for (i = 0; i < setup->n_outputs; i++)
{
MetaOutput *output;
MetaOutputTest *output_test;
int crtc_index;
MetaCrtc *crtc;
int preferred_mode_index;
MetaCrtcMode *preferred_mode;
MetaCrtcMode **modes;
int n_modes;
int j;
MetaCrtc **possible_crtcs;
int n_possible_crtcs;
int scale;
gboolean is_laptop_panel;
const char *serial;
g_autoptr (MetaOutputInfo) output_info = NULL;
crtc_index = setup->outputs[i].crtc;
if (crtc_index == -1)
crtc = NULL;
else
crtc = g_list_nth_data (test_setup->crtcs, crtc_index);
preferred_mode_index = setup->outputs[i].preferred_mode;
if (preferred_mode_index == -1)
preferred_mode = NULL;
else
preferred_mode = g_list_nth_data (test_setup->modes,
preferred_mode_index);
n_modes = setup->outputs[i].n_modes;
modes = g_new0 (MetaCrtcMode *, n_modes);
for (j = 0; j < n_modes; j++)
{
int mode_index;
mode_index = setup->outputs[i].modes[j];
modes[j] = g_list_nth_data (test_setup->modes, mode_index);
}
n_possible_crtcs = setup->outputs[i].n_possible_crtcs;
possible_crtcs = g_new0 (MetaCrtc *, n_possible_crtcs);
for (j = 0; j < n_possible_crtcs; j++)
{
int possible_crtc_index;
possible_crtc_index = setup->outputs[i].possible_crtcs[j];
possible_crtcs[j] = g_list_nth_data (test_setup->crtcs,
possible_crtc_index);
}
scale = setup->outputs[i].scale;
if (scale < 1)
scale = 1;
is_laptop_panel = setup->outputs[i].is_laptop_panel;
serial = setup->outputs[i].serial;
if (!serial)
serial = "0x123456";
output_info = meta_output_info_new ();
output_info->name = (is_laptop_panel
? g_strdup_printf ("eDP-%d", ++n_laptop_panels)
: g_strdup_printf ("DP-%d", ++n_normal_panels));
output_info->vendor = g_strdup ("MetaProduct's Inc.");
output_info->product = g_strdup ("MetaMonitor");
output_info->serial = g_strdup (serial);
if (setup->outputs[i].hotplug_mode)
{
output_info->hotplug_mode_update = TRUE;
output_info->suggested_x = setup->outputs[i].suggested_x;
output_info->suggested_y = setup->outputs[i].suggested_y;
}
else if (flags & MONITOR_TEST_FLAG_NO_STORED)
{
output_info->hotplug_mode_update = TRUE;
output_info->suggested_x = -1;
output_info->suggested_y = -1;
}
output_info->width_mm = setup->outputs[i].width_mm;
output_info->height_mm = setup->outputs[i].height_mm;
output_info->subpixel_order = COGL_SUBPIXEL_ORDER_UNKNOWN;
output_info->preferred_mode = preferred_mode;
output_info->n_modes = n_modes;
output_info->modes = modes;
output_info->n_possible_crtcs = n_possible_crtcs;
output_info->possible_crtcs = possible_crtcs;
output_info->n_possible_clones = 0;
output_info->possible_clones = NULL;
output_info->connector_type = (is_laptop_panel ? META_CONNECTOR_TYPE_eDP
: META_CONNECTOR_TYPE_DisplayPort);
output_info->tile_info = setup->outputs[i].tile_info;
output_info->panel_orientation_transform =
setup->outputs[i].panel_orientation_transform;
output = g_object_new (META_TYPE_OUTPUT_TEST,
"id", (uint64_t) i,
"gpu", test_get_gpu (),
"info", output_info,
NULL);
output_test = META_OUTPUT_TEST (output);
output_test->scale = scale;
if (crtc)
{
MetaOutputAssignment output_assignment;
output_assignment = (MetaOutputAssignment) {
.is_underscanning = setup->outputs[i].is_underscanning,
};
meta_output_assign_crtc (output, crtc, &output_assignment);
}
test_setup->outputs = g_list_append (test_setup->outputs, output);
}
return test_setup;
}
static void
check_expected_scales (MetaMonitor *monitor,
MetaMonitorMode *monitor_mode,
MetaMonitorScalesConstraint constraints,
int n_expected_scales,
float *expected_scales)
{
g_autofree float *scales = NULL;
int n_supported_scales;
int width, height;
int i;
scales = meta_monitor_calculate_supported_scales (monitor, monitor_mode,
constraints,
&n_supported_scales);
g_assert_cmpint (n_expected_scales, ==, n_supported_scales);
meta_monitor_mode_get_resolution (monitor_mode, &width, &height);
for (i = 0; i < n_supported_scales; i++)
{
g_assert_cmpfloat (scales[i], >, 0.0);
g_assert_cmpfloat_with_epsilon (scales[i], expected_scales[i], 0.000001);
if (!(constraints & META_MONITOR_SCALES_CONSTRAINT_NO_FRAC))
{
/* Also ensure that the scale will generate an integral resolution */
g_assert_cmpfloat (fmodf (width / scales[i], 1.0), ==, 0.0);
g_assert_cmpfloat (fmodf (height / scales[i], 1.0), ==, 0.0);
}
if (i > 0)
{
/* And that scales are sorted and unique */
g_assert_cmpfloat (scales[i], >, scales[i-1]);
g_assert_false (G_APPROX_VALUE (scales[i], scales[i-1], 0.000001));
}
}
}
void check_monitor_scales (MonitorTestCaseExpect *expect,
MetaMonitorScalesConstraint scales_constraints)
{
MetaBackend *backend = meta_get_backend ();
MetaMonitorManager *monitor_manager =
meta_backend_get_monitor_manager (backend);
GList *monitors;
GList *l;
int i;
monitors = meta_monitor_manager_get_monitors (monitor_manager);
g_assert_cmpuint (g_list_length (monitors), ==, expect->n_monitors);
for (l = monitors, i = 0; l; l = l->next, i++)
{
MetaMonitor *monitor = l->data;
MonitorTestCaseMonitor *expected_monitor = &expect->monitors[i];
GList *modes = meta_monitor_get_modes (monitor);
GList *k;
int j;
g_debug ("Checking monitor %d", i);
g_assert_cmpuint (g_list_length (modes), ==, expected_monitor->n_modes);
for (j = 0, k = modes; k; k = k->next, j++)
{
MetaMonitorMode *monitor_mode = k->data;
MetaMonitorTestCaseMonitorMode *expected_mode =
&expected_monitor->modes[j];
int width, height;
meta_monitor_mode_get_resolution (monitor_mode, &width, &height);
g_debug ("Checking %s scaling values for mode %dx%d",
(scales_constraints & META_MONITOR_SCALES_CONSTRAINT_NO_FRAC) ?
"integer" : "fractional", width, height);
g_assert_cmpint (width, ==, expected_mode->width);
g_assert_cmpint (height, ==, expected_mode->height);
check_expected_scales (monitor, monitor_mode, scales_constraints,
expected_mode->n_scales,
expected_mode->scales);
}
}
}