|
GnuCash 2.4.99
|
00001 /* Copyright (C) 2005, Chris Shoemaker <c.shoemaker@cox.net> 00002 * 00003 * This program is free software; you can redistribute it and/or 00004 * modify it under the terms of the GNU General Public License as 00005 * published by the Free Software Foundation; either version 2 of 00006 * the License, or (at your option) any later version. 00007 * 00008 * This program is distributed in the hope that it will be useful, 00009 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00010 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00011 * GNU General Public License for more details. 00012 * 00013 * You should have received a copy of the GNU General Public License 00014 * along with this program; if not, contact: 00015 * 00016 * Free Software Foundation Voice: +1-617-542-5942 00017 * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652 00018 * Boston, MA 02110-1301, USA gnu@gnu.org 00019 */ 00020 00021 #include "config.h" 00022 00023 #include <stdio.h> 00024 #include <stdlib.h> 00025 #include <glib.h> 00026 00027 #include "test-stuff.h" 00028 #include "Recurrence.h" 00029 #include "gnc-engine.h" 00030 00031 static QofBook *book; 00032 00033 static void check_valid(GDate *next, GDate *ref, GDate *start, 00034 guint16 mult, PeriodType pt, WeekendAdjust wadj) 00035 { 00036 gboolean valid; 00037 gint startToNext; 00038 /* FIXME: The WeekendAdjust argument is completely ignored for 00039 now. */ 00040 00041 valid = g_date_valid(next); 00042 if (pt == PERIOD_ONCE && g_date_compare(start, ref) <= 0) 00043 do_test(!valid, "incorrectly valid"); 00044 else 00045 do_test(valid, "incorrectly invalid"); 00046 00047 if (!valid) return; 00048 00049 do_test(g_date_compare(ref, next) < 0, 00050 "next date not strictly later than ref date"); 00051 startToNext = g_date_get_julian(next) - g_date_get_julian(start); 00052 00053 // Phase test 00054 switch (pt) 00055 { 00056 case PERIOD_YEAR: 00057 do_test((g_date_get_year(next) - g_date_get_year(start)) % mult == 0, 00058 "year period phase wrong"); // redundant 00059 mult *= 12; 00060 // fall through 00061 case PERIOD_END_OF_MONTH: 00062 if (pt == PERIOD_END_OF_MONTH) 00063 do_test(g_date_is_last_of_month(next), "end of month phase wrong"); 00064 // fall through 00065 case PERIOD_LAST_WEEKDAY: 00066 case PERIOD_NTH_WEEKDAY: 00067 case PERIOD_MONTH: 00068 { 00069 gint monthdiff; 00070 GDateDay day_start, day_next; 00071 00072 monthdiff = (g_date_get_month(next) - g_date_get_month(start)) + 00073 12 * (g_date_get_year(next) - g_date_get_year(start)); 00074 do_test(monthdiff % mult == 0, "month or year phase wrong"); 00075 00076 if (pt == PERIOD_NTH_WEEKDAY || pt == PERIOD_LAST_WEEKDAY) 00077 { 00078 guint sweek, nweek; 00079 00080 do_test(g_date_get_weekday(next) == g_date_get_weekday(start), 00081 "weekday phase wrong"); 00082 sweek = (g_date_get_day(start) - 1) / 7; 00083 nweek = (g_date_get_day(next) - 1) / 7; 00084 00085 /* 3 cases: either the weeks agree, OR 'next' didn't have 00086 5 of the weekday that 'start' did, so it's only the 00087 4th, OR 'start' didn't have 5 of the weekday that 00088 'next' does and we want the LAST weekday, so it's the 00089 5th of that weekday */ 00090 do_test(sweek == nweek || 00091 (sweek == 4 && nweek == 3 && (g_date_get_day(next) + 7) > 00092 g_date_get_days_in_month( 00093 g_date_get_month(next), g_date_get_year(next))) || 00094 (sweek == 3 && nweek == 4 && (pt == PERIOD_LAST_WEEKDAY)), 00095 "week of month phase wrong"); 00096 00097 } 00098 else 00099 { 00100 day_start = g_date_get_day(start); 00101 day_next = g_date_get_day(next); 00102 if (day_start < 28) 00103 do_test(day_start == day_next, "dom don't match"); 00104 else if (pt != PERIOD_END_OF_MONTH) 00105 { 00106 // the end of month case was already checked above. near 00107 // the end of the month, the days should still agree, 00108 // unless they can't because of a short month. 00109 do_test(day_start == day_next || g_date_is_last_of_month(next), 00110 "dom don't match and next is not eom"); 00111 } 00112 } 00113 } 00114 break; 00115 case PERIOD_WEEK: 00116 mult *= 7; 00117 // fall through 00118 case PERIOD_DAY: 00119 do_test((startToNext % mult) == 0, "week or day period phase wrong"); 00120 break; 00121 case PERIOD_ONCE: 00122 do_test(startToNext == 0, "period once not on start date"); 00123 break; 00124 default: 00125 do_test(FALSE, "invalid PeriodType"); 00126 break; 00127 } 00128 00129 } 00130 00131 #define NUM_DATES_TO_TEST 300 00132 #define NUM_DATES_TO_TEST_REF 300 00133 #define NUM_MULT_TO_TEST 10 00134 #define JULIAN_START 2003*365 // years have to be < 10000 00135 00136 /* Mult of zero is usually not valid, but it gets regularized to 1, so 00137 the effect is just that we end up testing mult of 1 twice, plus the 00138 regularization. */ 00139 static void test_all() 00140 { 00141 Recurrence r; 00142 GDate d_start, d_start_reg; 00143 GDate d_ref, d_next; 00144 guint16 mult, mult_reg; 00145 PeriodType pt, pt_reg; 00146 WeekendAdjust wadj, wadj_reg; 00147 gint32 j1, j2; 00148 gint i_ref; 00149 00150 for (pt = PERIOD_ONCE; pt < NUM_PERIOD_TYPES; pt++) 00151 { 00152 for (wadj = WEEKEND_ADJ_NONE; wadj < NUM_WEEKEND_ADJS; wadj++) 00153 { 00154 for (j1 = JULIAN_START; j1 < JULIAN_START + NUM_DATES_TO_TEST; j1++) 00155 { 00156 g_date_set_julian(&d_start, j1); 00157 for (i_ref = 0; i_ref < NUM_DATES_TO_TEST_REF; i_ref++) 00158 { 00159 j2 = (guint32) get_random_int_in_range(1, 1 << 19); 00160 g_date_set_julian(&d_ref, j2); 00161 00162 for (mult = 0; mult < NUM_MULT_TO_TEST; mult++) 00163 { 00164 recurrenceSet(&r, mult, pt, &d_start, wadj); 00165 pt_reg = recurrenceGetPeriodType(&r); 00166 d_start_reg = recurrenceGetDate(&r); 00167 mult_reg = recurrenceGetMultiplier(&r); 00168 wadj_reg = recurrenceGetWeekendAdjust(&r); 00169 00170 recurrenceNextInstance(&r, &d_ref, &d_next); 00171 check_valid(&d_next, &d_ref, &d_start_reg, 00172 mult_reg, pt_reg, wadj_reg); 00173 00174 } 00175 } 00176 } 00177 } 00178 } 00179 } 00180 00181 static gboolean test_equal(GDate *d1, GDate *d2) 00182 { 00183 if (!do_test(g_date_compare(d1, d2) == 0, "dates don't match")) 00184 { 00185 gchar s1[21]; 00186 gchar s2[21]; 00187 g_date_strftime(s1, 20, "%x", d1); 00188 g_date_strftime(s2, 20, "%x", d2); 00189 00190 printf("%s != %s\n", s1, s2); 00191 return FALSE; 00192 } 00193 return TRUE; 00194 } 00195 00196 00197 static void test_specific(PeriodType pt, guint16 mult, 00198 GDateMonth sm, GDateDay sd, GDateYear sy, 00199 GDateMonth rm, GDateDay rd, GDateYear ry, 00200 GDateMonth nm, GDateDay nd, GDateYear ny) 00201 { 00202 GDate start; 00203 GDate ref, next, true_next; 00204 Recurrence r; 00205 00206 g_date_set_dmy(&start, sd, sm, sy); 00207 g_date_set_dmy(&ref, rd, rm, ry); 00208 g_date_set_dmy(&true_next, nd, nm, ny); 00209 00210 00211 recurrenceSet(&r, mult, pt, &start, WEEKEND_ADJ_NONE); 00212 recurrenceNextInstance(&r, &ref, &next); 00213 00214 check_valid(&next, &ref, &start, mult, pt, WEEKEND_ADJ_NONE); 00215 if (!test_equal(&next, &true_next)) 00216 { 00217 gchar s1[21], s2[21], s3[21]; 00218 g_date_strftime(s1, 20, "%x", &start); 00219 g_date_strftime(s2, 20, "%x", &ref); 00220 g_date_strftime(s3, 20, "%x", &true_next); 00221 printf("pt = %d; mult = %d; start = %s; ref = %s; true_next = %s\n", 00222 pt, mult, s1, s2, s3); 00223 } 00224 } 00225 00226 #if 0 00227 static void test_nth(GDateMonth sm, GDateDay sd, GDateYear sy, 00228 GDateMonth nm, GDateDay nd, GDateYear ny, 00229 gint diff, PeriodType pt) 00230 { 00231 GDate start, next; 00232 gint d; 00233 00234 g_date_set_dmy(&start, sd, sm, sy); 00235 g_date_set_dmy(&next, nd, nm, ny); 00236 00237 d = nth_weekday_compare(&start, &next, pt); 00238 do_test(d == diff, "nth"); 00239 } 00240 00241 static void test_nth_compare() 00242 { 00243 test_nth(4, 1, 2005, 4, 2, 2005, -1, PERIOD_NTH_WEEKDAY); 00244 test_nth(4, 1, 2005, 4, 4, 2005, -3, PERIOD_NTH_WEEKDAY); 00245 test_nth(4, 1, 2005, 4, 7, 2005, -6, PERIOD_NTH_WEEKDAY); 00246 test_nth(4, 1, 2005, 4, 8, 2005, -7, PERIOD_NTH_WEEKDAY); 00247 test_nth(4, 1, 2005, 4, 14, 2005, -13, PERIOD_NTH_WEEKDAY); 00248 test_nth(4, 1, 2005, 4, 30, 2005, -29, PERIOD_NTH_WEEKDAY); 00249 test_nth(4, 1, 2005, 5, 1, 2005, 5, PERIOD_NTH_WEEKDAY); 00250 test_nth(4, 1, 2005, 5, 5, 2005, 1, PERIOD_NTH_WEEKDAY); 00251 test_nth(4, 1, 2005, 5, 6, 2005, 0, PERIOD_NTH_WEEKDAY); 00252 test_nth(4, 1, 2005, 5, 7, 2005, -1, PERIOD_NTH_WEEKDAY); 00253 test_nth(4, 1, 2005, 5, 8, 2005, -2, PERIOD_NTH_WEEKDAY); 00254 test_nth(4, 1, 2005, 5, 21, 2005, -15, PERIOD_NTH_WEEKDAY); 00255 00256 00257 test_nth(4, 6, 2005, 4, 1, 2005, 5, PERIOD_NTH_WEEKDAY); 00258 test_nth(4, 6, 2005, 4, 4, 2005, 2, PERIOD_NTH_WEEKDAY); 00259 test_nth(4, 6, 2005, 4, 6, 2005, 0, PERIOD_NTH_WEEKDAY); 00260 test_nth(4, 6, 2005, 4, 9, 2005, -3, PERIOD_NTH_WEEKDAY); 00261 test_nth(4, 6, 2005, 4, 11, 2005, -5, PERIOD_NTH_WEEKDAY); 00262 test_nth(4, 6, 2005, 4, 13, 2005, -7, PERIOD_NTH_WEEKDAY); 00263 test_nth(4, 6, 2005, 4, 14, 2005, -8, PERIOD_NTH_WEEKDAY); 00264 test_nth(4, 6, 2005, 4, 29, 2005, -23, PERIOD_NTH_WEEKDAY); 00265 00266 test_nth(4, 12, 2005, 4, 1, 2005, 11, PERIOD_NTH_WEEKDAY); 00267 test_nth(4, 12, 2005, 4, 4, 2005, 8, PERIOD_NTH_WEEKDAY); 00268 test_nth(4, 12, 2005, 4, 11, 2005, 1, PERIOD_NTH_WEEKDAY); 00269 test_nth(4, 12, 2005, 4, 12, 2005, 0, PERIOD_NTH_WEEKDAY); 00270 test_nth(4, 12, 2005, 4, 13, 2005, -1, PERIOD_NTH_WEEKDAY); 00271 test_nth(4, 12, 2005, 4, 17, 2005, -5, PERIOD_NTH_WEEKDAY); 00272 test_nth(4, 12, 2005, 4, 19, 2005, -7, PERIOD_NTH_WEEKDAY); 00273 test_nth(4, 12, 2005, 4, 28, 2005, -16, PERIOD_NTH_WEEKDAY); 00274 00275 test_nth(4, 29, 2005, 4, 30, 2005, -1, PERIOD_LAST_WEEKDAY); 00276 test_nth(4, 29, 2005, 5, 1, 2005, 26, PERIOD_LAST_WEEKDAY); 00277 test_nth(4, 29, 2005, 7, 9, 2005, 20, PERIOD_LAST_WEEKDAY); 00278 test_nth(4, 29, 2005, 7, 31, 2005, -2, PERIOD_LAST_WEEKDAY); 00279 00280 test_nth(4, 28, 2005, 4, 30, 2005, -2, PERIOD_LAST_WEEKDAY); 00281 test_nth(4, 28, 2005, 5, 1, 2005, 25, PERIOD_LAST_WEEKDAY); 00282 test_nth(4, 28, 2005, 7, 9, 2005, 19, PERIOD_LAST_WEEKDAY); 00283 test_nth(4, 28, 2005, 7, 31, 2005, -3, PERIOD_LAST_WEEKDAY); 00284 test_nth(4, 28, 2005, 9, 21, 2005, 8, PERIOD_LAST_WEEKDAY); 00285 00286 } 00287 #endif 00288 static void test_some() 00289 { 00290 test_specific(PERIOD_NTH_WEEKDAY, 1, 4, 1, 2005, 4, 2, 2005, 5, 6, 2005); 00291 test_specific(PERIOD_NTH_WEEKDAY, 1, 7, 14, 2005, 11, 15, 2005, 12, 8, 2005); 00292 test_specific(PERIOD_NTH_WEEKDAY, 1, 7, 14, 2005, 11, 5, 2005, 11, 10, 2005); 00293 test_specific(PERIOD_NTH_WEEKDAY, 1, 4, 1, 2005, 4, 2, 2005, 5, 6, 2005); 00294 test_specific(PERIOD_NTH_WEEKDAY, 1, 4, 1, 2005, 4, 2, 2005, 5, 6, 2005); 00295 00296 test_specific(PERIOD_LAST_WEEKDAY, 1, 4, 29, 2005, 4, 30, 2005, 5, 27, 2005); 00297 test_specific(PERIOD_LAST_WEEKDAY, 1, 4, 29, 2005, 5, 1, 2005, 5, 27, 2005); 00298 test_specific(PERIOD_LAST_WEEKDAY, 1, 4, 29, 2005, 7, 9, 2005, 7, 29, 2005); 00299 test_specific(PERIOD_LAST_WEEKDAY, 1, 4, 29, 2005, 6, 30, 2005, 7, 29, 2005); 00300 test_specific(PERIOD_LAST_WEEKDAY, 1, 4, 29, 2005, 7, 31, 2005, 8, 26, 2005); 00301 00302 test_specific(PERIOD_NTH_WEEKDAY, 2, 4, 27, 2005, 4, 27, 2005, 6, 22, 2005); 00303 //exit(1); 00304 //return; 00305 test_specific(PERIOD_YEAR, 3, 9, 8, 838, 6, 30, 1094, 9, 8, 1096); 00306 test_specific(PERIOD_YEAR, 2, 9, 8, 838, 6, 30, 1094, 9, 8, 1094); 00307 test_specific(PERIOD_YEAR, 1, 1, 10, 1000, 1, 5, 1002, 1, 10, 1002); 00308 //return; 00309 test_specific(PERIOD_MONTH, 1, 1, 12, 1, 2, 6, 1, 2, 12, 1); 00310 00311 test_specific(PERIOD_MONTH, 1, 1, 12, 1, 2, 12, 1, 3, 12, 1); 00312 test_specific(PERIOD_MONTH, 1, 1, 12, 1, 2, 20, 1, 3, 12, 1); 00313 test_specific(PERIOD_MONTH, 1, 1, 30, 1, 2, 28, 1, 3, 30, 1); 00314 test_specific(PERIOD_MONTH, 1, 1, 30, 1, 2, 27, 1, 2, 28, 1); 00315 test_specific(PERIOD_MONTH, 1, 2, 28, 1, 3, 30, 1, 4, 28, 1); 00316 00317 test_specific(PERIOD_END_OF_MONTH, 1, 2, 28, 1, 3, 30, 1, 3, 31, 1); 00318 test_specific(PERIOD_END_OF_MONTH, 5, 4, 30, 1, 4, 21, 1, 4, 30, 1); 00319 test_specific(PERIOD_END_OF_MONTH, 5, 2, 28, 1, 5, 21, 1, 7, 31, 1); 00320 00321 test_specific(PERIOD_YEAR, 7, 6, 8, 199, 9, 10, 1338, 6, 8, 1340); 00322 test_specific(PERIOD_YEAR, 2, 9, 8, 838, 6, 30, 1094, 9, 8, 1094); 00323 00324 test_specific(PERIOD_YEAR, 1, 5, 2, 13, 1, 11, 101, 5, 2, 101); 00325 test_specific(PERIOD_DAY, 7, 4, 1, 2000, 4, 8, 2000, 4, 15, 2000); 00326 } 00327 00328 static void test_use() 00329 { 00330 Recurrence *r; 00331 00332 r = g_new(Recurrence, 1); 00333 do_test(r != NULL, "allocation"); 00334 g_free(r); 00335 } 00336 00337 static void test_main() 00338 { 00339 00340 book = qof_book_new (); 00341 00342 test_use(); 00343 00344 test_some(); 00345 00346 test_all(); 00347 00348 qof_book_destroy (book); 00349 } 00350 00351 00352 int 00353 main (int argc, char **argv) 00354 { 00355 qof_init(); 00356 00357 g_log_set_always_fatal( G_LOG_LEVEL_CRITICAL | G_LOG_LEVEL_WARNING ); 00358 00359 #if 0 00360 set_success_print(TRUE); 00361 #endif 00362 00363 test_main(); 00364 00365 print_test_results(); 00366 return get_rv(); 00367 }
1.7.4