]> granicus.if.org Git - vnstat/commitdiff
workaround and test for libgd/libgd#351
authorTeemu Toivola <git@humdi.net>
Fri, 12 Oct 2018 20:44:08 +0000 (23:44 +0300)
committerTeemu Toivola <git@humdi.net>
Fri, 12 Oct 2018 20:44:08 +0000 (23:44 +0300)
.gitignore
src/image.c
src/image.h
tests/dbsql_tests.c
tests/dbsql_tests.h
tests/image_tests.c
tests/vnstat_tests.c
tests/vnstat_tests.h

index 5294ba93d55fb99aadfb3d64461f419bc244529f..71a2b66f99d750760d6c5f6ac35448451fd8ed53 100644 (file)
@@ -11,6 +11,7 @@ vnstati
 *.trs
 coverage
 vnstat_tests
+vnstati_check.png
 check_vnstat
 testdir
 Makefile
index fb445277e69a1dec93a9971c77cd25a0d08a3d48..a3bb23e5d7f43f404e956098552b3b4c147e62c1 100644 (file)
@@ -240,29 +240,60 @@ void drawdonut(IMAGECONTENT *ic, const int x, const int y, const float rxp, cons
                } else {
                        txarc = (int)(360 * (txp / (float)100));
                }
+       }
+
+       // background filled circle
+       gdImageFilledArc(ic->im, x, y, DOUTRAD, DOUTRAD, 0, 360, ic->cbgoffset, 0);
 
-               /* fix possible graphical glitch */
-               if (!rxarc) {
-                       rxarc = 1;
+       if (txarc) {
+               gdImageFilledArc(ic->im, x, y, DOUTRAD, DOUTRAD, 270, 270+txarc, ic->ctxd, gdEdged|gdNoFill);
+               if (txarc >= 5) {
+                       gdImageFill(ic->im, x+1, y-(DOUTRAD/2-3), ic->ctx);
                }
+               gdImageFilledArc(ic->im, x, y, DINRAD, DINRAD, 270, 270+txarc, ic->ctxd, gdEdged|gdNoFill);
+       }
 
-               if (!txarc) {
-                       txarc = 1;
+       if (rxarc) {
+               gdImageFilledArc(ic->im, x, y, DOUTRAD, DOUTRAD, 270+txarc, 270+txarc+rxarc, ic->crxd, gdEdged|gdNoFill);
+               if (rxarc >= 5) {
+                       gdImageFill(ic->im, x+(DOUTRAD/2-3)*cos(((270*2+2*txarc+rxarc)/2)*M_PI/180), y+(DOUTRAD/2-3)*sin(((270*2+2*txarc+rxarc)/2)*M_PI/180), ic->crx);
                }
+               gdImageFilledArc(ic->im, x, y, DINRAD, DINRAD, 270+txarc, 270+txarc+rxarc, ic->crxd, gdEdged|gdNoFill);
        }
 
-       gdImageFilledArc(ic->im, x, y, DOUTRAD, DOUTRAD, 0, 360, ic->cbgoffset, 0);
+       // remove center from background filled circle, making it a donut
+       gdImageFilledArc(ic->im, x, y, DINRAD-2, DINRAD-2, 0, 360, ic->cbackground, 0);
+}
+
+void drawdonut_libgd_native(IMAGECONTENT *ic, const int x, const int y, const float rxp, const float txp)
+{
+       int rxarc = 0, txarc = 0;
 
        if ( (int)(rxp + txp) > 0 ) {
+               rxarc = (int)(360 * (rxp / (float)100));
+               if ( (int)(rxp + txp) == 100 ) {
+                       txarc = 360 - rxarc;
+               } else {
+                       txarc = (int)(360 * (txp / (float)100));
+               }
+       }
+
+       // background filled circle
+       gdImageFilledArc(ic->im, x, y, DOUTRAD, DOUTRAD, 0, 360, ic->cbgoffset, 0);
+
+       if (txarc) {
                gdImageFilledArc(ic->im, x, y, DOUTRAD, DOUTRAD, 270, 270+txarc, ic->ctx, 0);
                gdImageFilledArc(ic->im, x, y, DOUTRAD, DOUTRAD, 270, 270+txarc, ic->ctxd, gdEdged|gdNoFill);
+               gdImageFilledArc(ic->im, x, y, DINRAD, DINRAD, 270, 270+txarc, ic->ctxd, gdEdged|gdNoFill);
+       }
+
+       if (rxarc) {
                gdImageFilledArc(ic->im, x, y, DOUTRAD, DOUTRAD, 270+txarc, 270+txarc+rxarc, ic->crx, 0);
                gdImageFilledArc(ic->im, x, y, DOUTRAD, DOUTRAD, 270+txarc, 270+txarc+rxarc, ic->crxd, gdEdged|gdNoFill);
-
-               gdImageFilledArc(ic->im, x, y, DINRAD, DINRAD, 270, 270+txarc, ic->ctxd, gdEdged|gdNoFill);
                gdImageFilledArc(ic->im, x, y, DINRAD, DINRAD, 270+txarc, 270+txarc+rxarc, ic->crxd, gdEdged|gdNoFill);
        }
 
+       // remove center from background filled circle, making it a donut
        gdImageFilledArc(ic->im, x, y, DINRAD-2, DINRAD-2, 0, 360, ic->cbackground, 0);
 }
 
index cfd92bac2038b75f9342671bf2a4a4277da122af..bb7d130c4034d2fe03dc62c9c99148d01f2baa38 100644 (file)
@@ -39,6 +39,7 @@ void drawlegend(IMAGECONTENT *ic, const int x, const int y);
 void drawbar(IMAGECONTENT *ic, const int x, const int y, const int len, const uint64_t rx, const uint64_t tx, const uint64_t max);
 void drawpole(IMAGECONTENT *ic, const int x, const int y, const int len, const uint64_t rx, const uint64_t tx, const uint64_t max);
 void drawdonut(IMAGECONTENT *ic, const int x, const int y, const float rxp, const float txp);
+void drawdonut_libgd_native(IMAGECONTENT *ic, const int x, const int y, const float rxp, const float txp);
 void drawhours(IMAGECONTENT *ic, int x, int y, int rate);
 void drawhourly(IMAGECONTENT *ic, int rate);
 void drawlist(IMAGECONTENT *ic, const char *listname);
index 46b074dabfd58f2640b68759b0bc111cc2221a4e..b177e8ef56fa2e2574ec097e2f93b73e2809997e 100644 (file)
@@ -963,21 +963,6 @@ START_TEST(db_validate_with_high_version)
 }
 END_TEST
 
-uint64_t get_timestamp(const int year, const int month, const int day, const int hour, const int minute)
-{
-       struct tm stm;
-
-       memset(&stm, 0, sizeof(struct tm));
-       stm.tm_year = year - 1900;
-       stm.tm_mon = month - 1;
-       stm.tm_mday = day;
-       stm.tm_hour = hour;
-       stm.tm_min = minute;
-       stm.tm_isdst = -1;
-
-       return (uint64_t)mktime(&stm);
-}
-
 void range_test_month_setup(void)
 {
        int ret, i;
index 121e8d8e2c6f20a97f8df1857e5c34d6d7686ef6..6dcc97b64322cd97c45ee91c2b4632998a0dff6a 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef DBSQL_TESTS_H
 #define DBSQL_TESTS_H
 
-uint64_t get_timestamp(const int year, const int month, const int day, const int hour, const int minute);
 void range_test_month_setup(void);
 void range_test_hour_setup(void);
 void add_dbsql_tests(Suite *s);
index f4b3867f897cbed2522ff59f4042478e440766f9..e54a1905a6f63e95dbe8f9cf55557c7ab4e87fb8 100644 (file)
@@ -400,6 +400,206 @@ START_TEST(hourly_imagescaling_rate_1000)
 }
 END_TEST
 
+START_TEST(output_check)
+{
+       int ret, x, y;
+       IMAGECONTENT ic;
+       FILE *pngout;
+
+       x = 1060;
+       y = 420;
+
+       defaultcfg();
+       initimagecontent(&ic);
+       ic.im = gdImageCreate(x, y);
+       colorinit(&ic);
+       ic.interface.updated = get_timestamp(2001, 2, 3, 4, 5);
+       layoutinit(&ic, "vnstati output reference test", x, y);
+
+       pngout = fopen("vnstati_check.png", "w");
+       ck_assert_ptr_ne(pngout, NULL);
+
+       drawlegend(&ic, 40, 30);
+
+       /* line 1 */
+       x = 40;
+       y = 80;
+       gdImageStringUp(ic.im, gdFontGetSmall(), 1, y+105, (unsigned char*)"libgd bug workaround", ic.ctext);
+       drawdonut(&ic, x, y, 0, 0);
+       drawdonut(&ic, x+55, y, 50.0, 50.0);
+       gdImageString(ic.im, gdFontGetSmall(), x-20, y+30, (unsigned char*)"0/0 - 50/50", ic.ctext);
+
+       x += 130;
+       drawdonut(&ic, x, y, 100.0, 0);
+       drawdonut(&ic, x+55, y, 0, 100.0);
+       gdImageString(ic.im, gdFontGetSmall(), x-20, y+30, (unsigned char*)"100/0 - 0/100", ic.ctext);
+
+       x += 130;
+       drawdonut(&ic, x, y, 60.0, 40.0);
+       drawdonut(&ic, x+55, y, 40.0, 60.0);
+       gdImageString(ic.im, gdFontGetSmall(), x-20, y+30, (unsigned char*)"60/40 - 40/60", ic.ctext);
+
+       x += 130;
+       drawdonut(&ic, x, y, 75.0, 25.0);
+       drawdonut(&ic, x+55, y, 25.0, 75.0);
+       gdImageString(ic.im, gdFontGetSmall(), x-20, y+30, (unsigned char*)"75/25 - 25/75", ic.ctext);
+
+       x += 130;
+       drawdonut(&ic, x, y, 90.0, 10.0);
+       drawdonut(&ic, x+55, y, 10.0, 90.0);
+       gdImageString(ic.im, gdFontGetSmall(), x-20, y+30, (unsigned char*)"90/10 - 10/90", ic.ctext);
+
+       x += 130;
+       drawdonut(&ic, x, y, 95.0, 5.0);
+       drawdonut(&ic, x+55, y, 5.0, 95.0);
+       gdImageString(ic.im, gdFontGetSmall(), x-20, y+30, (unsigned char*)"95/5 - 5/95", ic.ctext);
+
+       x += 130;
+       drawdonut(&ic, x, y, 99.0, 1.0);
+       drawdonut(&ic, x+55, y, 1.0, 99.0);
+       gdImageString(ic.im, gdFontGetSmall(), x-20, y+30, (unsigned char*)"99/1 - 1/99", ic.ctext);
+
+       x += 130;
+       drawdonut(&ic, x, y, 99.9, 0.1);
+       drawdonut(&ic, x+55, y, 0.1, 99.9);
+       gdImageString(ic.im, gdFontGetSmall(), x-20, y+30, (unsigned char*)"99.9/0.1 - 0.1/99.9", ic.ctext);
+
+       /* line 2 */
+       x = 40;
+       y = 160;
+       drawdonut(&ic, x, y, 0, 0);
+       drawdonut(&ic, x+55, y, 25.0, 25.0);
+       gdImageString(ic.im, gdFontGetSmall(), x-20, y+30, (unsigned char*)"0/0 - 25/25", ic.ctext);
+
+       x += 130;
+       drawdonut(&ic, x, y, 50.0, 0);
+       drawdonut(&ic, x+55, y, 0, 50.0);
+       gdImageString(ic.im, gdFontGetSmall(), x-20, y+30, (unsigned char*)"50/0 - 0/50", ic.ctext);
+
+       x += 130;
+       drawdonut(&ic, x, y, 40.0, 30.0);
+       drawdonut(&ic, x+55, y, 30.0, 40.0);
+       gdImageString(ic.im, gdFontGetSmall(), x-20, y+30, (unsigned char*)"40/30 - 30/40", ic.ctext);
+
+       x += 130;
+       drawdonut(&ic, x, y, 30.0, 20.0);
+       drawdonut(&ic, x+55, y, 20.0, 30.0);
+       gdImageString(ic.im, gdFontGetSmall(), x-20, y+30, (unsigned char*)"30/20 - 20/30", ic.ctext);
+
+       x += 130;
+       drawdonut(&ic, x, y, 20.0, 10.0);
+       drawdonut(&ic, x+55, y, 10.0, 20.0);
+       gdImageString(ic.im, gdFontGetSmall(), x-20, y+30, (unsigned char*)"20/10 - 10/20", ic.ctext);
+
+       x += 130;
+       drawdonut(&ic, x, y, 15.0, 5.0);
+       drawdonut(&ic, x+55, y, 5.0, 15.0);
+       gdImageString(ic.im, gdFontGetSmall(), x-20, y+30, (unsigned char*)"15/5 - 5/15", ic.ctext);
+
+       x += 130;
+       drawdonut(&ic, x, y, 10.0, 1.0);
+       drawdonut(&ic, x+55, y, 1.0, 10.0);
+       gdImageString(ic.im, gdFontGetSmall(), x-20, y+30, (unsigned char*)"10/1 - 1/10", ic.ctext);
+
+       x += 130;
+       drawdonut(&ic, x, y, 1.0, 0.1);
+       drawdonut(&ic, x+55, y, 0.1, 1.0);
+       gdImageString(ic.im, gdFontGetSmall(), x-20, y+30, (unsigned char*)"1.0/0.1 - 0.1/1.0", ic.ctext);
+
+       /* line 3 */
+       x = 40;
+       y = 270;
+       gdImageStringUp(ic.im, gdFontGetSmall(), 1, y+105, (unsigned char*)"libgd native", ic.ctext);
+       drawdonut_libgd_native(&ic, x, y, 0, 0);
+       drawdonut_libgd_native(&ic, x+55, y, 50.0, 50.0);
+       gdImageString(ic.im, gdFontGetSmall(), x-20, y+30, (unsigned char*)"0/0 - 50/50", ic.ctext);
+
+       x += 130;
+       drawdonut_libgd_native(&ic, x, y, 100.0, 0);
+       drawdonut_libgd_native(&ic, x+55, y, 0, 100.0);
+       gdImageString(ic.im, gdFontGetSmall(), x-20, y+30, (unsigned char*)"100/0 - 0/100", ic.ctext);
+
+       x += 130;
+       drawdonut_libgd_native(&ic, x, y, 60.0, 40.0);
+       drawdonut_libgd_native(&ic, x+55, y, 40.0, 60.0);
+       gdImageString(ic.im, gdFontGetSmall(), x-20, y+30, (unsigned char*)"60/40 - 40/60", ic.ctext);
+
+       x += 130;
+       drawdonut_libgd_native(&ic, x, y, 75.0, 25.0);
+       drawdonut_libgd_native(&ic, x+55, y, 25.0, 75.0);
+       gdImageString(ic.im, gdFontGetSmall(), x-20, y+30, (unsigned char*)"75/25 - 25/75", ic.ctext);
+
+       x += 130;
+       drawdonut_libgd_native(&ic, x, y, 90.0, 10.0);
+       drawdonut_libgd_native(&ic, x+55, y, 10.0, 90.0);
+       gdImageString(ic.im, gdFontGetSmall(), x-20, y+30, (unsigned char*)"90/10 - 10/90", ic.ctext);
+
+       x += 130;
+       drawdonut_libgd_native(&ic, x, y, 95.0, 5.0);
+       drawdonut_libgd_native(&ic, x+55, y, 5.0, 95.0);
+       gdImageString(ic.im, gdFontGetSmall(), x-20, y+30, (unsigned char*)"95/5 - 5/95", ic.ctext);
+
+       x += 130;
+       drawdonut_libgd_native(&ic, x, y, 99.0, 1.0);
+       drawdonut_libgd_native(&ic, x+55, y, 1.0, 99.0);
+       gdImageString(ic.im, gdFontGetSmall(), x-20, y+30, (unsigned char*)"99/1 - 1/99", ic.ctext);
+
+       x += 130;
+       drawdonut_libgd_native(&ic, x, y, 99.9, 0.1);
+       drawdonut_libgd_native(&ic, x+55, y, 0.1, 99.9);
+       gdImageString(ic.im, gdFontGetSmall(), x-20, y+30, (unsigned char*)"99.9/0.1 - 0.1/99.9", ic.ctext);
+
+       /* line 4 */
+       x = 40;
+       y = 350;
+       drawdonut_libgd_native(&ic, x, y, 0, 0);
+       drawdonut_libgd_native(&ic, x+55, y, 25.0, 25.0);
+       gdImageString(ic.im, gdFontGetSmall(), x-20, y+30, (unsigned char*)"0/0 - 25/25", ic.ctext);
+
+       x += 130;
+       drawdonut_libgd_native(&ic, x, y, 50.0, 0);
+       drawdonut_libgd_native(&ic, x+55, y, 0, 50.0);
+       gdImageString(ic.im, gdFontGetSmall(), x-20, y+30, (unsigned char*)"50/0 - 0/50", ic.ctext);
+
+       x += 130;
+       drawdonut_libgd_native(&ic, x, y, 40.0, 30.0);
+       drawdonut_libgd_native(&ic, x+55, y, 30.0, 40.0);
+       gdImageString(ic.im, gdFontGetSmall(), x-20, y+30, (unsigned char*)"40/30 - 30/40", ic.ctext);
+
+       x += 130;
+       drawdonut_libgd_native(&ic, x, y, 30.0, 20.0);
+       drawdonut_libgd_native(&ic, x+55, y, 20.0, 30.0);
+       gdImageString(ic.im, gdFontGetSmall(), x-20, y+30, (unsigned char*)"30/20 - 20/30", ic.ctext);
+
+       x += 130;
+       drawdonut_libgd_native(&ic, x, y, 20.0, 10.0);
+       drawdonut_libgd_native(&ic, x+55, y, 10.0, 20.0);
+       gdImageString(ic.im, gdFontGetSmall(), x-20, y+30, (unsigned char*)"20/10 - 10/20", ic.ctext);
+
+       x += 130;
+       drawdonut_libgd_native(&ic, x, y, 15.0, 5.0);
+       drawdonut_libgd_native(&ic, x+55, y, 5.0, 15.0);
+       gdImageString(ic.im, gdFontGetSmall(), x-20, y+30, (unsigned char*)"15/5 - 5/15", ic.ctext);
+
+       x += 130;
+       drawdonut_libgd_native(&ic, x, y, 10.0, 1.0);
+       drawdonut_libgd_native(&ic, x+55, y, 1.0, 10.0);
+       gdImageString(ic.im, gdFontGetSmall(), x-20, y+30, (unsigned char*)"10/1 - 1/10", ic.ctext);
+
+       x += 130;
+       drawdonut_libgd_native(&ic, x, y, 1.0, 0.1);
+       drawdonut_libgd_native(&ic, x+55, y, 0.1, 1.0);
+       gdImageString(ic.im, gdFontGetSmall(), x-20, y+30, (unsigned char*)"1.0/0.1 - 0.1/1.0", ic.ctext);
+
+
+
+       gdImagePng(ic.im, pngout);
+       ret = fclose(pngout);
+       ck_assert_int_eq(ret, 0);
+       gdImageDestroy(ic.im);
+}
+END_TEST
+
 void add_image_tests(Suite *s)
 {
        TCase *tc_image = tcase_create("Image");
@@ -419,5 +619,6 @@ void add_image_tests(Suite *s)
        tcase_add_test(tc_image, hourly_imagescaling_normal);
        tcase_add_test(tc_image, hourly_imagescaling_rate_1024);
        tcase_add_test(tc_image, hourly_imagescaling_rate_1000);
+       tcase_add_test(tc_image, output_check);
        suite_add_tcase(s, tc_image);
 }
index e68d64d94c470633a829974511ffbf5bc93cfe19..866059d67e7f141748f6be81d5faf03cd81a3d3c 100644 (file)
@@ -303,3 +303,18 @@ int fake_sys_class_net(const char *iface, const int rx, const int tx, const int
 
        return 1;
 }
+
+uint64_t get_timestamp(const int year, const int month, const int day, const int hour, const int minute)
+{
+       struct tm stm;
+
+       memset(&stm, 0, sizeof(struct tm));
+       stm.tm_year = year - 1900;
+       stm.tm_mon = month - 1;
+       stm.tm_mday = day;
+       stm.tm_hour = hour;
+       stm.tm_min = minute;
+       stm.tm_isdst = -1;
+
+       return (uint64_t)mktime(&stm);
+}
index e642b88cb861dc54d2d9c4b449419108b8ed5578..7e83d4b4b6e2ba697c6e0923f8d81b2631cb436a 100644 (file)
@@ -15,6 +15,7 @@ int create_zerosize_dbfile(const char *iface);
 int check_dbfile_exists(const char *iface, const int minsize);
 int fake_proc_net_dev(const char *mode, const char *iface, const int rx, const int tx, const int rxp, const int txp);
 int fake_sys_class_net(const char *iface, const int rx, const int tx, const int rxp, const int txp, const int speed);
+uint64_t get_timestamp(const int year, const int month, const int day, const int hour, const int minute);
 
 #ifndef TESTDIR
 #define TESTDIR "testdir"