1 /* Test of ordered set data type implementation.
2    Copyright (C) 2020-2021 Free Software Foundation, Inc.
3    Written by Bruno Haible <bruno@clisp.org>, 2020.
4 
5    This program is free software: you can redistribute it and/or modify
6    it under the terms of the GNU General Public License as published by
7    the Free Software Foundation; either version 3 of the License, or
8    (at your option) any later version.
9 
10    This program is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13    GNU General Public License for more details.
14 
15    You should have received a copy of the GNU General Public License
16    along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
17 
18 static void
action(const void * str,void * data)19 action (const void *str, void *data)
20 {
21   ((char *) str)[0] += *(int *)data;
22 }
23 
24 static void
test_update(gl_oset_implementation_t implementation)25 test_update (gl_oset_implementation_t implementation)
26 {
27   char A[2] = "A";
28   char B[2] = "B";
29   char C[2] = "C";
30   char D[2] = "D";
31 
32   gl_oset_t set1 =
33     gl_oset_nx_create_empty (implementation, (gl_setelement_compar_fn) strcmp, NULL);
34   ASSERT (set1 != NULL);
35 
36   /* Fill the set.  */
37   ASSERT (gl_oset_nx_add (set1, C) == 1);
38   ASSERT (gl_oset_nx_add (set1, A) == 1);
39   ASSERT (gl_oset_nx_add (set1, B) == 1);
40   ASSERT (gl_oset_nx_add (set1, D) == 1);
41 
42   /* Verify that set1 = ["A", "B", "C", "D"].  */
43   {
44     gl_oset_iterator_t iter = gl_oset_iterator (set1);
45     const void *elt;
46 
47     ASSERT (gl_oset_iterator_next (&iter, &elt));
48     ASSERT (elt == A);
49     ASSERT (gl_oset_iterator_next (&iter, &elt));
50     ASSERT (elt == B);
51     ASSERT (gl_oset_iterator_next (&iter, &elt));
52     ASSERT (elt == C);
53     ASSERT (gl_oset_iterator_next (&iter, &elt));
54     ASSERT (elt == D);
55     ASSERT (!gl_oset_iterator_next (&iter, &elt));
56   }
57 
58   /* Make a side effect on an element in the set, that moves the element.  */
59   {
60     int data = 'G' - 'B';
61     ASSERT (gl_oset_update (set1, B, action, &data) == 1);
62   }
63   /* Verify that set1 = ["A", "C", "D", "G"].  */
64   {
65     gl_oset_iterator_t iter = gl_oset_iterator (set1);
66     const void *elt;
67 
68     ASSERT (gl_oset_iterator_next (&iter, &elt));
69     ASSERT (elt == A);
70     ASSERT (gl_oset_iterator_next (&iter, &elt));
71     ASSERT (elt == C);
72     ASSERT (gl_oset_iterator_next (&iter, &elt));
73     ASSERT (elt == D);
74     ASSERT (gl_oset_iterator_next (&iter, &elt));
75     ASSERT (elt == B);
76     ASSERT (!gl_oset_iterator_next (&iter, &elt));
77   }
78 
79   /* Make a side effect on an element in the set, that does not move the
80      element.  */
81   {
82     int data = 'E' - 'D';
83     ASSERT (gl_oset_update (set1, D, action, &data) == 0);
84   }
85   /* Verify that set1 = ["A", "C", "E", "G"].  */
86   {
87     gl_oset_iterator_t iter = gl_oset_iterator (set1);
88     const void *elt;
89 
90     ASSERT (gl_oset_iterator_next (&iter, &elt));
91     ASSERT (elt == A);
92     ASSERT (gl_oset_iterator_next (&iter, &elt));
93     ASSERT (elt == C);
94     ASSERT (gl_oset_iterator_next (&iter, &elt));
95     ASSERT (elt == D);
96     ASSERT (gl_oset_iterator_next (&iter, &elt));
97     ASSERT (elt == B);
98     ASSERT (!gl_oset_iterator_next (&iter, &elt));
99   }
100 
101   /* Make a side effect on an element in the set, that provokes a
102      collision.  */
103   {
104     int data = 'G' - 'A';
105     ASSERT (gl_oset_update (set1, A, action, &data) == -1);
106   }
107   /* Verify that set1 = ["C", "E", "G"].  */
108   {
109     gl_oset_iterator_t iter = gl_oset_iterator (set1);
110     const void *elt;
111 
112     ASSERT (gl_oset_iterator_next (&iter, &elt));
113     ASSERT (elt == C);
114     ASSERT (gl_oset_iterator_next (&iter, &elt));
115     ASSERT (elt == D);
116     ASSERT (gl_oset_iterator_next (&iter, &elt));
117     ASSERT (elt == B);
118     ASSERT (!gl_oset_iterator_next (&iter, &elt));
119   }
120 
121   /* Make a side effect on an element that is not in the set.  */
122   {
123     int data = 'R' - 'G';
124     ASSERT (gl_oset_update (set1, A, action, &data) == 0);
125   }
126   /* Verify that set1 = ["C", "E", "G"].  */
127   {
128     gl_oset_iterator_t iter = gl_oset_iterator (set1);
129     const void *elt;
130 
131     ASSERT (gl_oset_iterator_next (&iter, &elt));
132     ASSERT (elt == C);
133     ASSERT (gl_oset_iterator_next (&iter, &elt));
134     ASSERT (elt == D);
135     ASSERT (gl_oset_iterator_next (&iter, &elt));
136     ASSERT (elt == B);
137     ASSERT (!gl_oset_iterator_next (&iter, &elt));
138   }
139 
140   gl_oset_free (set1);
141 }
142