1 /* This file is a test-case for GEGL
2  *
3  * GEGL is free software; you can redistribute it and/or
4  * modify it under the terms of the GNU Lesser General Public
5  * License as published by the Free Software Foundation; either
6  * version 3 of the License, or (at your option) any later version.
7  *
8  * GEGL is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11  * Lesser General Public License for more details.
12  *
13  * You should have received a copy of the GNU Lesser General Public
14  * License along with GEGL; if not, see <https://www.gnu.org/licenses/>.
15  */
16 #include <gegl.h>
17 
18 typedef struct {
19     GeglBuffer *buffer;
20     GeglRectangle buffer_extent;
21     const Babl *buffer_format;
22 
23     guint buffer_changed_called;
24     GeglRectangle buffer_changed_rect;
25 } TestCase;
26 
27 GeglRectangle null_rect = {0, 0, 0, 0};
28 
29 gboolean    test_gegl_rectangle_equal(const GeglRectangle *expected, const GeglRectangle *actual);
30 TestCase *  test_case_new(void);
31 void        handle_buffer_changed(GeglBuffer *buffer, const GeglRectangle *rect, gpointer user_data);
32 void        test_buffer_change_signal_on_set(void);
33 void        test_buffer_change_signal_with_iter(guint access_method, guint expected_signal_calls);
34 void        test_buffer_change_signal_with_iter_write(void);
35 void        test_buffer_change_signal_with_iter_readwrite(void);
36 void        test_buffer_no_change_signal_with_iter_read(void);
37 
38 gboolean
test_gegl_rectangle_equal(const GeglRectangle * expected,const GeglRectangle * actual)39 test_gegl_rectangle_equal(const GeglRectangle *expected, const GeglRectangle *actual)
40 {
41     gboolean equal = gegl_rectangle_equal(expected, actual);
42     if (!equal) {
43         g_warning("GeglRectangle(%d, %d %dx%d) != GeglRectangle(%d, %d %dx%d)",
44                   expected->x, expected->y, expected->width, expected->height,
45                   actual->x, actual->y, actual->width, actual->height);
46     }
47     return equal;
48 }
49 
50 TestCase *
test_case_new(void)51 test_case_new(void)
52 {
53     TestCase *test_case = g_new(TestCase, 1);
54 
55     test_case->buffer_extent.x = 0;
56     test_case->buffer_extent.y = 0;
57     test_case->buffer_extent.width = 500;
58     test_case->buffer_extent.height = 500;
59     test_case->buffer_format = babl_format("RGBA u8");
60     test_case->buffer = gegl_buffer_new(&test_case->buffer_extent, test_case->buffer_format);
61 
62     test_case->buffer_changed_called = 0;
63     test_case->buffer_changed_rect = null_rect;
64     return test_case;
65 }
66 
67 
68 void
handle_buffer_changed(GeglBuffer * buffer,const GeglRectangle * rect,gpointer user_data)69 handle_buffer_changed(GeglBuffer *buffer, const GeglRectangle *rect, gpointer user_data)
70 {
71     TestCase *t = (TestCase *)user_data;
72     t->buffer_changed_called++;
73     t->buffer_changed_rect = *rect;
74 }
75 
76 /* Test that 'changed' signal is emitted on gegl_buffer_set */
77 void
test_buffer_change_signal_on_set(void)78 test_buffer_change_signal_on_set(void)
79 {
80     TestCase *test_case = test_case_new();
81     GeglRectangle rect = {0, 0, 100, 100};
82     char *tmp = g_malloc(rect.height*rect.width*1*4);
83 
84     gegl_buffer_signal_connect(test_case->buffer, "changed", (GCallback)handle_buffer_changed, test_case);
85 
86     gegl_buffer_set(test_case->buffer, &rect, 0, test_case->buffer_format, tmp, GEGL_AUTO_ROWSTRIDE);
87 
88     g_assert_cmpint(test_case->buffer_changed_called, ==, 1);
89     g_assert(test_gegl_rectangle_equal(&(test_case->buffer_changed_rect), &rect));
90 
91     g_free(tmp);
92     g_free(test_case);
93 }
94 
95 /* Utility function to test emission of 'changed' signal on GeglBuffer
96  * when accessing with GeglBufferIterator.
97  * @access_method: GEGL_ACCESS_READ, GEGL_ACCESS_WRITE, GEGL_ACCESS_READWRITE
98  * @expected_signal_calls: Whether the 'changed' signal is expected to be emitted or not
99  */
100 void
test_buffer_change_signal_with_iter(guint access_method,guint expected_signal_calls)101 test_buffer_change_signal_with_iter(guint access_method, guint expected_signal_calls)
102 {
103     TestCase *test_case = test_case_new();
104     GeglRectangle rect = {0, 0, 100, 100};
105     char *tmp = g_malloc(rect.height*rect.width*1*4);
106     GeglBufferIterator *gi = gegl_buffer_iterator_new(test_case->buffer, &rect, 0,
107                                 test_case->buffer_format, access_method, GEGL_ABYSS_NONE, 1);
108 
109     gegl_buffer_signal_connect(test_case->buffer, "changed", (GCallback)handle_buffer_changed, test_case);
110 
111     while (gegl_buffer_iterator_next(gi)) {
112     }
113 
114     if (expected_signal_calls == 0)
115         rect = null_rect;
116 
117     g_assert(test_case->buffer_changed_called == expected_signal_calls);
118     g_assert(test_gegl_rectangle_equal(&(test_case->buffer_changed_rect), &rect));
119 
120     g_free(tmp);
121     g_free(test_case);
122 }
123 
124 /* Test that 'changed' signal is emitted once for gegl_buffer_iterator in WRITE mode */
125 void
test_buffer_change_signal_with_iter_write(void)126 test_buffer_change_signal_with_iter_write(void)
127 {
128     test_buffer_change_signal_with_iter(GEGL_ACCESS_WRITE, 1);
129 }
130 
131 /* Test that 'changed' signal is emitted once for gegl_buffer_iterator in READWRITE mode */
132 void
test_buffer_change_signal_with_iter_readwrite(void)133 test_buffer_change_signal_with_iter_readwrite(void)
134 {
135     test_buffer_change_signal_with_iter(GEGL_ACCESS_READWRITE, 1);
136 }
137 
138 /* Test that 'changed' signal is _not_ emitted on gegl_buffer_iterator in READ mode */
139 void
test_buffer_no_change_signal_with_iter_read(void)140 test_buffer_no_change_signal_with_iter_read(void)
141 {
142     test_buffer_change_signal_with_iter(GEGL_ACCESS_READ, 0);
143 }
144 
145 gint
main(gint argc,gchar ** argv)146 main(gint argc, gchar **argv)
147 {
148     babl_init();
149     gegl_init(&argc, &argv);
150     g_test_init (&argc, &argv, NULL);
151 
152     g_test_add_func ("/buffer/change/signal-on-set", test_buffer_change_signal_on_set);
153     g_test_add_func ("/buffer/change/no-signal-with-iter-read", test_buffer_no_change_signal_with_iter_read);
154     g_test_add_func ("/buffer/change/signal-with-iter-readwrite", test_buffer_change_signal_with_iter_readwrite);
155     g_test_add_func ("/buffer/change/signal-with-iter-write", test_buffer_change_signal_with_iter_write);
156     return g_test_run();
157 }
158