(root)/
glib-2.79.0/
glib/
tests/
base64.c
       1  #include <glib.h>
       2  #include <string.h>
       3  #include <stdlib.h>
       4  
       5  #define DATA_SIZE 1024
       6  #define BLOCK_SIZE 32
       7  #define NUM_BLOCKS 32
       8  static guchar global_data[DATA_SIZE];
       9  
      10  static void
      11  test_incremental (gboolean line_break,
      12                    gsize    length)
      13  {
      14    char *p;
      15    gsize len, decoded_len, max, input_len, block_size;
      16    int state, save;
      17    guint decoder_save;
      18    char *text;
      19    guchar *data2;
      20  
      21    data2 = g_malloc (length);
      22    text = g_malloc (length * 4);
      23  
      24    len = 0;
      25    state = 0;
      26    save = 0;
      27    input_len = 0;
      28    while (input_len < length)
      29      {
      30        block_size = MIN (BLOCK_SIZE, length - input_len);
      31        len += g_base64_encode_step (global_data + input_len, block_size,
      32                                     line_break, text + len, &state, &save);
      33        input_len += block_size;
      34      }
      35    len += g_base64_encode_close (line_break, text + len, &state, &save);
      36  
      37    if (line_break)
      38      max = length * 4 / 3 + length * 4 / (3 * 72) + 7;
      39    else
      40      max = length * 4 / 3 + 6;
      41  
      42    /* Check encoded length */
      43    g_assert_cmpint (len, <=, max);
      44  
      45    decoded_len = 0;
      46    state = 0;
      47    decoder_save = 0;
      48    p = text;
      49    while (len > 0)
      50      {
      51        int chunk_len = MIN (BLOCK_SIZE, len);
      52        decoded_len += g_base64_decode_step (p,
      53                                             chunk_len,
      54                                             data2 + decoded_len,
      55                                             &state, &decoder_save);
      56        p += chunk_len;
      57        len -= chunk_len;
      58      }
      59  
      60    g_assert_cmpmem (global_data, length, data2, decoded_len);
      61  
      62    g_free (text);
      63    g_free (data2);
      64  }
      65  
      66  static void
      67  test_incremental_break (gconstpointer d)
      68  {
      69    gint length = GPOINTER_TO_INT (d);
      70  
      71    test_incremental (TRUE, length);
      72  }
      73  
      74  static void
      75  test_incremental_nobreak (gconstpointer d)
      76  {
      77    gint length = GPOINTER_TO_INT (d);
      78  
      79    test_incremental (FALSE, length);
      80  }
      81  
      82  static void
      83  test_full (gconstpointer d)
      84  {
      85    gint length = GPOINTER_TO_INT (d);
      86    char *text;
      87    guchar *data2;
      88    gsize len;
      89  
      90    text = g_base64_encode (global_data, length);
      91    data2 = g_base64_decode (text, &len);
      92    g_free (text);
      93  
      94    g_assert_cmpmem (global_data, length, data2, len);
      95  
      96    g_free (data2);
      97  }
      98  
      99  struct MyRawData
     100  {
     101    gint length;   /* of data */
     102    guchar data[DATA_SIZE];
     103  };
     104  
     105  /* 100 pre-encoded string from data[] buffer. Data length from 1..100
     106   */
     107  static const char *ok_100_encode_strs[] = {
     108    "AA==",
     109    "AAE=",
     110    "AAEC",
     111    "AAECAw==",
     112    "AAECAwQ=",
     113    "AAECAwQF",
     114    "AAECAwQFBg==",
     115    "AAECAwQFBgc=",
     116    "AAECAwQFBgcI",
     117    "AAECAwQFBgcICQ==",
     118    "AAECAwQFBgcICQo=",
     119    "AAECAwQFBgcICQoL",
     120    "AAECAwQFBgcICQoLDA==",
     121    "AAECAwQFBgcICQoLDA0=",
     122    "AAECAwQFBgcICQoLDA0O",
     123    "AAECAwQFBgcICQoLDA0ODw==",
     124    "AAECAwQFBgcICQoLDA0ODxA=",
     125    "AAECAwQFBgcICQoLDA0ODxAR",
     126    "AAECAwQFBgcICQoLDA0ODxAREg==",
     127    "AAECAwQFBgcICQoLDA0ODxAREhM=",
     128    "AAECAwQFBgcICQoLDA0ODxAREhMU",
     129    "AAECAwQFBgcICQoLDA0ODxAREhMUFQ==",
     130    "AAECAwQFBgcICQoLDA0ODxAREhMUFRY=",
     131    "AAECAwQFBgcICQoLDA0ODxAREhMUFRYX",
     132    "AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGA==",
     133    "AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBk=",
     134    "AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBka",
     135    "AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGw==",
     136    "AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxw=",
     137    "AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwd",
     138    "AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHg==",
     139    "AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8=",
     140    "AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8g",
     141    "AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gIQ==",
     142    "AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISI=",
     143    "AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIj",
     144    "AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJA==",
     145    "AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCU=",
     146    "AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUm",
     147    "AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJw==",
     148    "AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJyg=",
     149    "AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygp",
     150    "AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKg==",
     151    "AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKis=",
     152    "AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKiss",
     153    "AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKissLQ==",
     154    "AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4=",
     155    "AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4v",
     156    "AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4vMA==",
     157    "AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4vMDE=",
     158    "AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4vMDEy",
     159    "AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4vMDEyMw==",
     160    "AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4vMDEyMzQ=",
     161    "AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4vMDEyMzQ1",
     162    "AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4vMDEyMzQ1Ng==",
     163    "AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4vMDEyMzQ1Njc=",
     164    "AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4vMDEyMzQ1Njc4",
     165    "AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4vMDEyMzQ1Njc4OQ==",
     166    "AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4vMDEyMzQ1Njc4OTo=",
     167    "AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4vMDEyMzQ1Njc4OTo7",
     168    "AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4vMDEyMzQ1Njc4OTo7PA==",
     169    "AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4vMDEyMzQ1Njc4OTo7PD0=",
     170    "AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4vMDEyMzQ1Njc4OTo7PD0+",
     171    "AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4vMDEyMzQ1Njc4OTo7PD0+Pw==",
     172    "AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4vMDEyMzQ1Njc4OTo7PD0+P0A=",
     173    "AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4vMDEyMzQ1Njc4OTo7PD0+P0BB",
     174    "AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4vMDEyMzQ1Njc4OTo7PD0+P0BBQg==",
     175    "AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4vMDEyMzQ1Njc4OTo7PD0+P0BBQkM=",
     176    "AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4vMDEyMzQ1Njc4OTo7PD0+P0BBQkNE",
     177    "AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4vMDEyMzQ1Njc4OTo7PD0+P0BBQkNERQ==",
     178    "AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4vMDEyMzQ1Njc4OTo7PD0+P0BBQkNERUY=",
     179    "AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4vMDEyMzQ1Njc4OTo7PD0+P0BBQkNERUZH",
     180    "AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4vMDEyMzQ1Njc4OTo7PD0+P0BBQkNERUZHSA==",
     181    "AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4vMDEyMzQ1Njc4OTo7PD0+P0BBQkNERUZHSEk=",
     182    "AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4vMDEyMzQ1Njc4OTo7PD0+P0BBQkNERUZHSElK",
     183    "AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4vMDEyMzQ1Njc4OTo7PD0+P0BBQkNERUZHSElKSw==",
     184    "AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4vMDEyMzQ1Njc4OTo7PD0+P0BBQkNERUZHSElKS0w=",
     185    "AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4vMDEyMzQ1Njc4OTo7PD0+P0BBQkNERUZHSElKS0xN",
     186    "AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4vMDEyMzQ1Njc4OTo7PD0+P0BBQkNERUZHSElKS0xNTg==",
     187    "AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4vMDEyMzQ1Njc4OTo7PD0+P0BBQkNERUZHSElKS0xNTk8=",
     188    "AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4vMDEyMzQ1Njc4OTo7PD0+P0BBQkNERUZHSElKS0xNTk9Q",
     189    "AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4vMDEyMzQ1Njc4OTo7PD0+P0BBQkNERUZHSElKS0xNTk9QUQ==",
     190    "AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4vMDEyMzQ1Njc4OTo7PD0+P0BBQkNERUZHSElKS0xNTk9QUVI=",
     191    "AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4vMDEyMzQ1Njc4OTo7PD0+P0BBQkNERUZHSElKS0xNTk9QUVJT",
     192    "AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4vMDEyMzQ1Njc4OTo7PD0+P0BBQkNERUZHSElKS0xNTk9QUVJTVA==",
     193    "AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4vMDEyMzQ1Njc4OTo7PD0+P0BBQkNERUZHSElKS0xNTk9QUVJTVFU=",
     194    "AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4vMDEyMzQ1Njc4OTo7PD0+P0BBQkNERUZHSElKS0xNTk9QUVJTVFVW",
     195    "AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4vMDEyMzQ1Njc4OTo7PD0+P0BBQkNERUZHSElKS0xNTk9QUVJTVFVWVw==",
     196    "AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4vMDEyMzQ1Njc4OTo7PD0+P0BBQkNERUZHSElKS0xNTk9QUVJTVFVWV1g=",
     197    "AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4vMDEyMzQ1Njc4OTo7PD0+P0BBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZ",
     198    "AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4vMDEyMzQ1Njc4OTo7PD0+P0BBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWg==",
     199    "AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4vMDEyMzQ1Njc4OTo7PD0+P0BBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWls=",
     200    "AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4vMDEyMzQ1Njc4OTo7PD0+P0BBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWltc",
     201    "AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4vMDEyMzQ1Njc4OTo7PD0+P0BBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWltcXQ==",
     202    "AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4vMDEyMzQ1Njc4OTo7PD0+P0BBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWltcXV4=",
     203    "AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4vMDEyMzQ1Njc4OTo7PD0+P0BBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWltcXV5f",
     204    "AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4vMDEyMzQ1Njc4OTo7PD0+P0BBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWltcXV5fYA==",
     205    "AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4vMDEyMzQ1Njc4OTo7PD0+P0BBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWltcXV5fYGE=",
     206    "AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4vMDEyMzQ1Njc4OTo7PD0+P0BBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWltcXV5fYGFi",
     207    "AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4vMDEyMzQ1Njc4OTo7PD0+P0BBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWltcXV5fYGFiYw==",
     208    NULL
     209  };
     210  
     211  static void
     212  generate_databuffer_for_base64 (struct MyRawData *p)
     213  {
     214    int i;
     215    for (i = 0; i < DATA_SIZE; i++)
     216      p->data[i] = i;
     217  }
     218  
     219  static void
     220  test_base64_encode (void)
     221  {
     222    int i;
     223    gint length = 1;
     224    char *text;
     225    struct MyRawData myraw;
     226  
     227    generate_databuffer_for_base64 (&myraw);
     228  
     229    for (i = 0; ok_100_encode_strs[i]; i++)
     230      {
     231        length = i + 1;
     232        text = g_base64_encode (myraw.data, length);
     233        g_assert_cmpstr (text, ==, ok_100_encode_strs[i]);
     234        /* printf ("\"%s\",\n",text); */
     235        g_free (text);
     236      }
     237  }
     238  
     239  /* Test that incremental and all-in-one encoding of strings of a length which
     240   * is not a multiple of 3 bytes behave the same, as the state carried over
     241   * between g_base64_encode_step() calls varies depending on how the input is
     242   * split up. This is like the test_base64_decode_smallblock() test, but for
     243   * encoding. */
     244  static void
     245  test_base64_encode_incremental_small_block (gconstpointer block_size_p)
     246  {
     247    gsize i;
     248    struct MyRawData myraw;
     249  
     250    g_test_bug ("https://bugzilla.gnome.org/show_bug.cgi?id=780066");
     251  
     252    generate_databuffer_for_base64 (&myraw);
     253  
     254    for (i = 0; ok_100_encode_strs[i] != NULL; i++)
     255      {
     256        const guint block_size = GPOINTER_TO_UINT (block_size_p);
     257        gchar *encoded_complete = NULL;
     258        gchar encoded_stepped[1024];
     259        gint state = 0, save = 0;
     260        gsize len_written, len_read, len_to_read, input_length;
     261  
     262        input_length = i + 1;
     263  
     264        /* Do it all at once. */
     265        encoded_complete = g_base64_encode (myraw.data, input_length);
     266  
     267        /* Split the data up so some number of bits remain after each step. */
     268        for (len_written = 0, len_read = 0; len_read < input_length; len_read += len_to_read)
     269          {
     270            len_to_read = MIN (block_size, input_length - len_read);
     271            len_written += g_base64_encode_step (myraw.data + len_read, len_to_read,
     272                                                 FALSE,
     273                                                 encoded_stepped + len_written,
     274                                                 &state, &save);
     275          }
     276  
     277        len_written += g_base64_encode_close (FALSE, encoded_stepped + len_written,
     278                                              &state, &save);
     279        g_assert_cmpuint (len_written, <, G_N_ELEMENTS (encoded_stepped));
     280  
     281        /* Nul-terminate to make string comparison easier. */
     282        encoded_stepped[len_written] = '\0';
     283  
     284        /* Compare results. They should be the same. */
     285        g_assert_cmpstr (encoded_complete, ==, ok_100_encode_strs[i]);
     286        g_assert_cmpstr (encoded_stepped, ==, encoded_complete);
     287  
     288        g_free (encoded_complete);
     289      }
     290  }
     291  
     292  static void
     293  decode_and_compare (const gchar            *datap,
     294                      const struct MyRawData *p)
     295  {
     296    guchar *data2;
     297    gsize len;
     298  
     299    data2 = g_base64_decode (datap, &len);
     300    g_assert_cmpmem (p->data, p->length, data2, len);
     301    g_free (data2);
     302  }
     303  
     304  static void
     305  decode_inplace_and_compare (const gchar            *datap,
     306                              const struct MyRawData *p)
     307  {
     308    gchar *data;
     309    guchar *data2;
     310    gsize len;
     311  
     312    data = g_strdup (datap);
     313    data2 = g_base64_decode_inplace (data, &len);
     314    g_assert_cmpmem (p->data, p->length, data2, len);
     315    g_free (data2);
     316  }
     317  
     318  static void
     319  test_base64_decode (void)
     320  {
     321    int i;
     322    struct MyRawData myraw;
     323  
     324    generate_databuffer_for_base64 (&myraw);
     325  
     326    for (i = 0; ok_100_encode_strs[i]; i++)
     327      {
     328        myraw.length = i + 1;
     329        decode_and_compare (ok_100_encode_strs[i], &myraw);
     330      }
     331  }
     332  
     333  static void
     334  test_base64_decode_inplace (void)
     335  {
     336    int i;
     337    struct MyRawData myraw;
     338  
     339    generate_databuffer_for_base64 (&myraw);
     340  
     341    for (i = 0; ok_100_encode_strs[i]; i++)
     342      {
     343        myraw.length = i + 1;
     344        decode_inplace_and_compare (ok_100_encode_strs[i], &myraw);
     345      }
     346  }
     347  
     348  static void
     349  test_base64_encode_decode (void)
     350  {
     351    int i;
     352    char *text;
     353    struct MyRawData myraw;
     354  
     355    generate_databuffer_for_base64 (&myraw);
     356  
     357    for (i = 0; i < DATA_SIZE; i++)
     358      {
     359        myraw.length = i + 1;
     360        text = g_base64_encode (myraw.data, myraw.length);
     361  
     362        decode_and_compare (text, &myraw);
     363  
     364        g_free (text);
     365      }
     366  }
     367  
     368  static void
     369  test_base64_decode_smallblock (gconstpointer blocksize_p)
     370  {
     371    const guint blocksize = GPOINTER_TO_UINT (blocksize_p);
     372    guint i;
     373  
     374    for (i = 0; ok_100_encode_strs[i]; i++)
     375      {
     376        const char *str = ok_100_encode_strs[i];
     377        const char *p;
     378        gsize len = strlen (str);
     379        gint state = 0;
     380        guint save = 0;
     381        guchar *decoded;
     382        gsize decoded_size = 0;
     383        guchar *decoded_atonce;
     384        gsize decoded_atonce_size = 0;
     385  
     386        decoded = g_malloc (len / 4 * 3 + 3);
     387  
     388        p = str;
     389        while (len > 0)
     390          {
     391            int chunk_len = MIN (blocksize, len);
     392            gsize size = g_base64_decode_step (p, chunk_len,
     393                                               decoded + decoded_size,
     394                                               &state, &save);
     395            decoded_size += size;
     396            len -= chunk_len;
     397            p += chunk_len;
     398          }
     399  
     400        decoded_atonce = g_base64_decode (str, &decoded_atonce_size);
     401  
     402        g_assert_cmpmem (decoded, decoded_size, decoded_atonce, decoded_atonce_size);
     403        
     404        g_free (decoded);
     405        g_free (decoded_atonce);
     406      }
     407  }
     408  
     409  /* Test that calling g_base64_encode (NULL, 0) returns correct output. This is
     410   * as per the first test vector in RFC 4648 §10.
     411   * https://tools.ietf.org/html/rfc4648#section-10 */
     412  static void
     413  test_base64_encode_empty (void)
     414  {
     415    gchar *encoded = NULL;
     416  
     417    g_test_bug ("https://gitlab.gnome.org/GNOME/glib/issues/1698");
     418  
     419    encoded = g_base64_encode (NULL, 0);
     420    g_assert_cmpstr (encoded, ==, "");
     421    g_free (encoded);
     422  
     423    encoded = g_base64_encode ((const guchar *) "", 0);
     424    g_assert_cmpstr (encoded, ==, "");
     425    g_free (encoded);
     426  }
     427  
     428  /* Test that calling g_base64_decode ("", *) returns correct output. This is
     429   * as per the first test vector in RFC 4648 §10. Note that calling
     430   * g_base64_decode (NULL, *) is not allowed.
     431   * https://tools.ietf.org/html/rfc4648#section-10 */
     432  static void
     433  test_base64_decode_empty (void)
     434  {
     435    guchar *decoded = NULL;
     436    gsize decoded_len;
     437  
     438    g_test_bug ("https://gitlab.gnome.org/GNOME/glib/issues/1698");
     439  
     440    decoded = g_base64_decode ("", &decoded_len);
     441    g_assert_cmpstr ((gchar *) decoded, ==, "");
     442    g_assert_cmpuint (decoded_len, ==, 0);
     443    g_free (decoded);
     444  }
     445  
     446  /* Check all the RFC 4648 test vectors for base 64 encoding from §10.
     447   * https://tools.ietf.org/html/rfc4648#section-10 */
     448  static void
     449  test_base64_encode_decode_rfc4648 (void)
     450  {
     451    const struct
     452      {
     453        const gchar *decoded;  /* technically this should be a byte array, but all the test vectors are ASCII strings */
     454        const gchar *encoded;
     455      }
     456    vectors[] =
     457      {
     458        { "", "" },
     459        { "f", "Zg==" },
     460        { "fo", "Zm8=" },
     461        { "foo", "Zm9v" },
     462        { "foob", "Zm9vYg==" },
     463        { "fooba", "Zm9vYmE=" },
     464        { "foobar", "Zm9vYmFy" },
     465      };
     466    gsize i;
     467  
     468    for (i = 0; i < G_N_ELEMENTS (vectors); i++)
     469      {
     470        gchar *encoded = NULL;
     471        guchar *decoded = NULL;
     472        gsize expected_decoded_len = strlen (vectors[i].decoded);
     473        gsize decoded_len;
     474  
     475        g_test_message ("Vector %" G_GSIZE_FORMAT ": %s", i, vectors[i].decoded);
     476  
     477        encoded = g_base64_encode ((const guchar *) vectors[i].decoded, expected_decoded_len);
     478        g_assert_cmpstr (encoded, ==, vectors[i].encoded);
     479  
     480        decoded = g_base64_decode (encoded, &decoded_len);
     481        g_assert_cmpstr ((gchar *) decoded, ==, vectors[i].decoded);
     482        g_assert_cmpuint (decoded_len, ==, expected_decoded_len);
     483  
     484        g_free (encoded);
     485        g_free (decoded);
     486      }
     487  }
     488  
     489  int
     490  main (int argc, char *argv[])
     491  {
     492    gint i;
     493  
     494    g_test_init (&argc, &argv, NULL);
     495  
     496    for (i = 0; i < DATA_SIZE; i++)
     497      global_data[i] = (guchar) i;
     498  
     499    g_test_add_data_func ("/base64/full/1", GINT_TO_POINTER (DATA_SIZE), test_full);
     500    g_test_add_data_func ("/base64/full/2", GINT_TO_POINTER (1), test_full);
     501    g_test_add_data_func ("/base64/full/3", GINT_TO_POINTER (2), test_full);
     502    g_test_add_data_func ("/base64/full/4", GINT_TO_POINTER (3), test_full);
     503  
     504    g_test_add_data_func ("/base64/encode/incremental/small-block/1", GINT_TO_POINTER (1), test_base64_encode_incremental_small_block);
     505    g_test_add_data_func ("/base64/encode/incremental/small-block/2", GINT_TO_POINTER (2), test_base64_encode_incremental_small_block);
     506    g_test_add_data_func ("/base64/encode/incremental/small-block/3", GINT_TO_POINTER (3), test_base64_encode_incremental_small_block);
     507    g_test_add_data_func ("/base64/encode/incremental/small-block/4", GINT_TO_POINTER (4), test_base64_encode_incremental_small_block);
     508  
     509    g_test_add_data_func ("/base64/incremental/nobreak/1", GINT_TO_POINTER (DATA_SIZE), test_incremental_nobreak);
     510    g_test_add_data_func ("/base64/incremental/break/1", GINT_TO_POINTER (DATA_SIZE), test_incremental_break);
     511  
     512    g_test_add_data_func ("/base64/incremental/nobreak/2", GINT_TO_POINTER (DATA_SIZE - 1), test_incremental_nobreak);
     513    g_test_add_data_func ("/base64/incremental/break/2", GINT_TO_POINTER (DATA_SIZE - 1), test_incremental_break);
     514  
     515    g_test_add_data_func ("/base64/incremental/nobreak/3", GINT_TO_POINTER (DATA_SIZE - 2), test_incremental_nobreak);
     516    g_test_add_data_func ("/base64/incremental/break/3", GINT_TO_POINTER (DATA_SIZE - 2), test_incremental_break);
     517  
     518    g_test_add_data_func ("/base64/incremental/nobreak/4-a", GINT_TO_POINTER (1), test_incremental_nobreak);
     519    g_test_add_data_func ("/base64/incremental/nobreak/4-b", GINT_TO_POINTER (2), test_incremental_nobreak);
     520    g_test_add_data_func ("/base64/incremental/nobreak/4-c", GINT_TO_POINTER (3), test_incremental_nobreak);
     521  
     522    g_test_add_func ("/base64/encode", test_base64_encode);
     523    g_test_add_func ("/base64/decode", test_base64_decode);
     524    g_test_add_func ("/base64/decode-inplace", test_base64_decode_inplace);
     525    g_test_add_func ("/base64/encode-decode", test_base64_encode_decode);
     526  
     527    g_test_add_data_func ("/base64/incremental/smallblock/1", GINT_TO_POINTER(1),
     528                          test_base64_decode_smallblock);
     529    g_test_add_data_func ("/base64/incremental/smallblock/2", GINT_TO_POINTER(2),
     530                          test_base64_decode_smallblock);
     531    g_test_add_data_func ("/base64/incremental/smallblock/3", GINT_TO_POINTER(3),
     532                          test_base64_decode_smallblock);
     533    g_test_add_data_func ("/base64/incremental/smallblock/4", GINT_TO_POINTER(4),
     534                          test_base64_decode_smallblock);
     535  
     536    g_test_add_func ("/base64/encode/empty", test_base64_encode_empty);
     537    g_test_add_func ("/base64/decode/empty", test_base64_decode_empty);
     538  
     539    g_test_add_func ("/base64/encode-decode/rfc4648", test_base64_encode_decode_rfc4648);
     540  
     541    return g_test_run ();
     542  }