]> git.ipfire.org Git - thirdparty/cups.git/commitdiff
Update testlang to test all locales (Issue #85)
authorMichael R Sweet <msweet@msweet.org>
Mon, 1 Mar 2021 12:26:58 +0000 (07:26 -0500)
committerMichael R Sweet <msweet@msweet.org>
Mon, 1 Mar 2021 12:26:58 +0000 (07:26 -0500)
Also refactored the locale test code into a separate function, updated the
output to be consistent with the other unit tests, and split out the macOS
language identifier tests.  Still need to move the PPD tests to the testppd
program.

CHANGES.md
cups/testlang.c

index 97428ebcfea57da745320e66f1207e3e5930fe61..589246c531c8132ea5562d82dbe0e3ab3d337c60 100644 (file)
@@ -4,6 +4,8 @@ Changes in OpenPrinting CUPS
 CUPS v2.4rc1 (Pending)
 ----------------------
 
+- The `testlang` unit test program now loops over all of the available locales
+  by default (Issue #85)
 - The `cupsfilter` command now shows error messages when options are used
   incorrectly (Issue #88)
 - Documentation fixes (Issue #92)
index 613ae32d66695a5c69e70c1ebe20a4be2f0cb576..057de84e79da43e73c696aefb426e26116e9ddfa 100644 (file)
@@ -5,10 +5,12 @@
  *
  *   ./testlang [-l locale] [-p ppd] ["String to localize"]
  *
- * Copyright 2007-2017 by Apple Inc.
- * Copyright 1997-2006 by Easy Software Products.
+ * Copyright © 2021 by OpenPrinting.
+ * Copyright © 2007-2017 by Apple Inc.
+ * Copyright © 1997-2006 by Easy Software Products.
  *
- * Licensed under Apache License v2.0.  See the file "LICENSE" for more information.
+ * Licensed under Apache License v2.0.  See the file "LICENSE" for more
+ * information.
  */
 
 /*
@@ -20,6 +22,7 @@
 #ifdef __APPLE__
 #  include <CoreFoundation/CoreFoundation.h>
 #endif /* __APPLE__ */
+#include <cups/dir.h>
 
 
 /*
  */
 
 static int     show_ppd(const char *filename);
+#ifdef __APPLE__
+static int     test_apple(void);
+#endif // __APPLE__
+static int     test_language(const char *locale);
 static int     test_string(cups_lang_t *language, const char *msgid);
 static void    usage(void);
 
@@ -39,23 +46,12 @@ int                                 /* O - Exit status */
 main(int  argc,                                /* I - Number of command-line arguments */
      char *argv[])                     /* I - Command-line arguments */
 {
-  int                  i;              /* Looping var */
-  const char           *opt;           /* Current option */
-  int                  errors = 0;     /* Number of errors */
-  int                  dotests = 1;    /* Do standard tests? */
-  cups_lang_t          *language = NULL;/* Message catalog */
-  cups_lang_t          *language2 = NULL;
-                                       /* Message catalog (second time) */
-  struct lconv         *loc;           /* Locale data */
-  char                 buffer[1024];   /* String buffer */
-  double               number;         /* Number */
-  static const char * const tests[] =  /* Test strings */
-  {
-    "1",
-    "-1",
-    "3",
-    "5.125"
-  };
+  int          i;                      /* Looping var */
+  const char   *opt;                   /* Current option */
+  int          errors = 0;             /* Number of errors */
+  int          dotests = 1;            /* Do standard tests? */
+  const char   *lang;                  /* Single language test? */
+  cups_lang_t  *language = NULL;       /* Message catalog */
 
 
  /*
@@ -86,11 +82,7 @@ main(int  argc,                              /* I - Number of command-line arguments */
                   return (1);
                 }
 
-               language  = cupsLangGet(argv[i]);
-               language2 = cupsLangGet(argv[i]);
-
-               setenv("LANG", argv[i], 1);
-               setenv("SOFTWARE", "CUPS/" CUPS_SVERSION, 1);
+                lang = argv[i];
                break;
 
            case 'p' :
@@ -101,12 +93,6 @@ main(int  argc,                             /* I - Number of command-line arguments */
                   return (1);
                 }
 
-                if (!language)
-                {
-                 language  = cupsLangDefault();
-                 language2 = cupsLangDefault();
-               }
-
                dotests = 0;
                errors += show_ppd(argv[i]);
                 break;
@@ -121,165 +107,62 @@ main(int  argc,                          /* I - Number of command-line arguments */
     else
     {
       if (!language)
-      {
-       language  = cupsLangDefault();
-       language2 = cupsLangDefault();
-      }
+        language = cupsLangGet(lang);
 
       dotests = 0;
       errors += test_string(language, argv[i]);
     }
   }
 
-  if (!language)
-  {
-    language  = cupsLangDefault();
-    language2 = cupsLangDefault();
-  }
-
-  if (language != language2)
-  {
-    errors ++;
-
-    puts("**** ERROR: Language cache did not work! ****");
-    puts("First result from cupsLangGet:");
-  }
-
-  printf("Language = \"%s\"\n", language->language);
-  printf("Encoding = \"%s\"\n", _cupsEncodingName(language->encoding));
-
   if (dotests)
   {
-    errors += test_string(language, "No");
-    errors += test_string(language, "Yes");
-
-    if (language != language2)
+    if (lang)
     {
-      puts("Second result from cupsLangGet:");
+     /*
+      * Test a single language...
+      */
 
-      printf("Language = \"%s\"\n", language2->language);
-      printf("Encoding = \"%s\"\n", _cupsEncodingName(language2->encoding));
-      printf("No       = \"%s\"\n", _cupsLangString(language2, "No"));
-      printf("Yes      = \"%s\"\n", _cupsLangString(language2, "Yes"));
+      errors += test_language(lang);
     }
-
-    loc = localeconv();
-
-    for (i = 0; i < (int)(sizeof(tests) / sizeof(tests[0])); i ++)
-    {
-      number = _cupsStrScand(tests[i], NULL, loc);
-
-      printf("_cupsStrScand(\"%s\") number=%f\n", tests[i], number);
-
-      _cupsStrFormatd(buffer, buffer + sizeof(buffer), number, loc);
-
-      printf("_cupsStrFormatd(%f) buffer=\"%s\"\n", number, buffer);
-
-      if (strcmp(buffer, tests[i]))
-      {
-       errors ++;
-       puts("**** ERROR: Bad formatted number! ****");
-      }
-    }
-
-#ifdef __APPLE__
-   /*
-    * Test all possible language IDs for compatibility with _cupsAppleLocale...
-    */
-
-    CFIndex     j,                      /* Looping var */
-                num_locales;            /* Number of locales */
-    CFArrayRef  locales;                /* Locales */
-    CFStringRef locale_id,              /* Current locale ID */
-                language_id;            /* Current language ID */
-    char        locale_str[256],        /* Locale ID C string */
-                language_str[256],      /* Language ID C string */
-                *bufptr;                /* Pointer to ".UTF-8" in POSIX locale */
-    size_t      buflen;                 /* Length of POSIX locale */
-#  if TEST_COUNTRY_CODES
-    CFIndex     k,                      /* Looping var */
-                num_country_codes;      /* Number of country codes */
-    CFArrayRef  country_codes;          /* Country codes */
-    CFStringRef country_code,           /* Current country code */
-                temp_id;                /* Temporary language ID */
-    char        country_str[256];       /* Country code C string */
-#  endif /* TEST_COUNTRY_CODES */
-
-    locales     = CFLocaleCopyAvailableLocaleIdentifiers();
-    num_locales = CFArrayGetCount(locales);
-
-#  if TEST_COUNTRY_CODES
-    country_codes     = CFLocaleCopyISOCountryCodes();
-    num_country_codes = CFArrayGetCount(country_codes);
-#  endif /* TEST_COUNTRY_CODES */
-
-    printf("%d locales are available:\n", (int)num_locales);
-
-    for (j = 0; j < num_locales; j ++)
+    else
     {
-      locale_id   = CFArrayGetValueAtIndex(locales, j);
-      language_id = CFLocaleCreateCanonicalLanguageIdentifierFromString(kCFAllocatorDefault, locale_id);
+     /*
+      * Test all locales we find in LOCALEDIR...
+      */
 
-      if (!locale_id || !CFStringGetCString(locale_id, locale_str, (CFIndex)sizeof(locale_str), kCFStringEncodingASCII))
-      {
-        printf("%d: FAIL (unable to get locale ID string)\n", (int)j + 1);
-        errors ++;
-        continue;
-      }
+      cups_dir_t       *dir;           /* Locale directory */
+      cups_dentry_t    *dent;          /* Directory entry */
 
-      if (!language_id || !CFStringGetCString(language_id, language_str, (CFIndex)sizeof(language_str), kCFStringEncodingASCII))
+      if ((dir = cupsDirOpen(getenv("LOCALEDIR"))) != NULL)
       {
-        printf("%d %s: FAIL (unable to get language ID string)\n", (int)j + 1, locale_str);
-        errors ++;
-        continue;
+       while ((dent = cupsDirRead(dir)) != NULL)
+         errors += test_language(dent->filename);
       }
-
-      if (!_cupsAppleLocale(language_id, buffer, sizeof(buffer)))
-      {
-        printf("%d %s(%s): FAIL (unable to convert language ID string to POSIX locale)\n", (int)j + 1, locale_str, language_str);
-        errors ++;
-        continue;
-      }
-
-      if ((bufptr = strstr(buffer, ".UTF-8")) != NULL)
-        buflen = (size_t)(bufptr - buffer);
       else
-        buflen = strlen(buffer);
-
-      if ((language = cupsLangGet(buffer)) == NULL)
-      {
-        printf("%d %s(%s): FAIL (unable to load POSIX locale \"%s\")\n", (int)j + 1, locale_str, language_str, buffer);
-        errors ++;
-        continue;
-      }
-
-      if (strncasecmp(language->language, buffer, buflen))
       {
-        printf("%d %s(%s): FAIL (unable to load POSIX locale \"%s\", got \"%s\")\n", (int)j + 1, locale_str, language_str, buffer, language->language);
-        errors ++;
-        continue;
+        // No LOCALEDIR, just use the default language...
+        errors += test_language(NULL);
       }
 
-      printf("%d %s(%s): PASS (POSIX locale is \"%s\")\n", (int)j + 1, locale_str, language_str, buffer);
+      cupsDirClose(dir);
     }
 
-    CFRelease(locales);
+#ifdef __APPLE__
+    errors += test_apple();
+#endif // __APPLE__
 
-#  if TEST_COUNTRY_CODES
-    CFRelease(country_codes);
-#  endif /* TEST_COUNTRY_CODES */
-#endif /* __APPLE__ */
+    if (!errors)
+      puts("ALL TESTS PASSED");
   }
 
-  if (errors == 0 && dotests)
-    puts("ALL TESTS PASSED");
-
   return (errors > 0);
 }
 
 
 /*
  * 'show_ppd()' - Show localized strings in a PPD file.
+ *
+ * TODO: Move this to the testppd program.
  */
 
 static int                             /* O - Number of errors */
@@ -327,15 +210,237 @@ show_ppd(const char *filename)           /* I - Filename */
 }
 
 
+#ifdef __APPLE__
+/*
+ * 'test_apple()' - Test macOS locale handing...
+ */
+
+static int                             /* O - Number of errors */
+test_apple(void)
+{
+  int          errors = 0;             /* Number of errors */
+  CFIndex      i,                      /* Looping var */
+               num_locales;            /* Number of locales */
+  CFArrayRef   locales;                /* Locales */
+  CFStringRef  locale_id,              /* Current locale ID */
+               language_id;            /* Current language ID */
+  cups_lang_t  *language = NULL;       /* Message catalog */
+  char         locale_str[256],        /* Locale ID C string */
+               language_str[256],      /* Language ID C string */
+               buffer[1024],           /* String buffer */
+               *bufptr;                /* Pointer to ".UTF-8" in POSIX locale */
+  size_t       buflen;                 /* Length of POSIX locale */
+
+
+ /*
+  * Test all possible language IDs for compatibility with _cupsAppleLocale...
+  */
+
+  locales     = CFLocaleCopyAvailableLocaleIdentifiers();
+  num_locales = CFArrayGetCount(locales);
+
+  printf("CFLocaleCopyAvailableLocaleIdentifiers: %d locales\n", (int)num_locales);
+
+  for (i = 0; i < num_locales; i ++)
+  {
+    locale_id   = CFArrayGetValueAtIndex(locales, i);
+    language_id = CFLocaleCreateCanonicalLanguageIdentifierFromString(kCFAllocatorDefault, locale_id);
+
+    printf("CFStringGetCString(locale_id %d): ", (int)i);
+    if (!locale_id || !CFStringGetCString(locale_id, locale_str, (CFIndex)sizeof(locale_str), kCFStringEncodingASCII))
+    {
+      puts("FAIL");
+      errors ++;
+      continue;
+    }
+    else
+      printf("PASS (\"%s\")\n", locale_str);
+
+    printf("CFStringGetCString(language_id %d): ", (int)i);
+    if (!language_id || !CFStringGetCString(language_id, language_str, (CFIndex)sizeof(language_str), kCFStringEncodingASCII))
+    {
+      printf("%d %s: FAIL (unable to get language ID string)\n", (int)i + 1, locale_str);
+      errors ++;
+      continue;
+    }
+    else
+      printf("PASS (\"%s\")\n", language_str);
+
+    printf("_cupsAppleLocale(\"%s\"): ", language_str);
+    if (!_cupsAppleLocale(language_id, buffer, sizeof(buffer)))
+    {
+      puts("FAIL");
+      errors ++;
+      continue;
+    }
+    else
+      printf("PASS (\"%s\")\n", buffer);
+
+    if ((bufptr = strstr(buffer, ".UTF-8")) != NULL)
+      buflen = (size_t)(bufptr - buffer);
+    else
+      buflen = strlen(buffer);
+
+    printf("cupsLangGet(\"%s\"): ", buffer);
+    if ((language = cupsLangGet(buffer)) == NULL)
+    {
+      puts("FAIL");
+      errors ++;
+      continue;
+    }
+    else if (strncasecmp(language->language, buffer, buflen))
+    {
+      printf("FAIL (got \"%s\")\n", language->language);
+      errors ++;
+      continue;
+    }
+    else
+      puts("PASS");
+  }
+
+  CFRelease(locales);
+
+  return (errors);
+}
+#endif // __APPLE__
+
+
+/*
+ * 'test_language()' - Test a specific language...
+ */
+
+static int                             /* O - Number of errors */
+test_language(const char *lang)                /* I - Locale language code, NULL for default */
+{
+  int          i;                      /* Looping var */
+  int          errors = 0;             /* Number of errors */
+  cups_lang_t  *language = NULL,       /* Message catalog */
+               *language2 = NULL;      /* Message catalog (second time) */
+  struct lconv *loc;                   /* Locale data */
+  char         buffer[1024];           /* String buffer */
+  double       number;                 /* Number */
+  static const char * const tests[] =  /* Test strings */
+  {
+    "1",
+    "-1",
+    "3",
+    "5.125"
+  };
+
+
+  // Override the locale environment as needed...
+  if (lang)
+  {
+    // Test the specified locale code...
+    setenv("LANG", lang, 1);
+    setenv("SOFTWARE", "CUPS/" CUPS_SVERSION, 1);
+
+    printf("cupsLangGet(\"%s\"): ", lang);
+    if ((language = cupsLangGet(lang)) == NULL)
+    {
+      puts("FAIL");
+      errors ++;
+    }
+    else if (strcasecmp(language->language, lang))
+    {
+      printf("FAIL (got \"%s\")\n", language->language);
+      errors ++;
+    }
+    else
+      puts("PASS");
+
+    printf("cupsLangGet(\"%s\") again: ", lang);
+    if ((language2 = cupsLangGet(lang)) == NULL)
+    {
+      puts("FAIL");
+      errors ++;
+    }
+    else if (strcasecmp(language2->language, lang))
+    {
+      printf("FAIL (got \"%s\")\n", language2->language);
+      errors ++;
+    }
+    else if (language2 != language)
+    {
+      puts("FAIL (cache failure)");
+      errors ++;
+    }
+    else
+      puts("PASS");
+  }
+  else
+  {
+    // Test the default locale...
+    fputs("cupsLangDefault: ", stdout);
+    if ((language = cupsLangDefault()) == NULL)
+    {
+      puts("FAIL");
+      errors ++;
+    }
+    else
+      puts("PASS");
+
+    fputs("cupsLangDefault again: ", stdout);
+    if ((language2 = cupsLangDefault()) == NULL)
+    {
+      puts("FAIL");
+      errors ++;
+    }
+    else if (language2 != language)
+    {
+      puts("FAIL (cache failure)");
+      errors ++;
+    }
+    else
+      puts("PASS");
+  }
+
+  printf("language->language: \"%s\"\n", language->language);
+  printf("_cupsEncodingName(language): \"%s\"\n", _cupsEncodingName(language->encoding));
+
+  errors += test_string(language, "No");
+  errors += test_string(language, "Yes");
+
+  if (language != language2)
+  {
+    printf("language2->language: \"%s\"\n", language2->language);
+    printf("_cupsEncodingName(language2): \"%s\"\n", _cupsEncodingName(language2->encoding));
+  }
+
+  loc = localeconv();
+
+  for (i = 0; i < (int)(sizeof(tests) / sizeof(tests[0])); i ++)
+  {
+    number = _cupsStrScand(tests[i], NULL, loc);
+
+    printf("_cupsStrScand(\"%s\"): %f\n", tests[i], number);
+
+    _cupsStrFormatd(buffer, buffer + sizeof(buffer), number, loc);
+
+    printf("_cupsStrFormatd(%f): ", number);
+
+    if (strcmp(buffer, tests[i]))
+    {
+      errors ++;
+      printf("FAIL (got \"%s\")\n", buffer);
+    }
+    else
+      puts("PASS");
+  }
+
+  return (errors);
+}
+
+
 /*
  * 'test_string()' - Test the localization of a string.
  */
 
-static int                            /* O - 1 on failure, 0 on success */
-test_string(cups_lang_t *language,    /* I - Language */
-            const char  *msgid)       /* I - Message */
+static int                             /* O - 1 on failure, 0 on success */
+test_string(cups_lang_t *language,     /* I - Language */
+            const char  *msgid)                /* I - Message */
 {
-  const char  *msgstr;                /* Localized string */
+  const char  *msgstr;                 /* Localized string */
 
 
  /*
@@ -345,19 +450,20 @@ test_string(cups_lang_t *language,    /* I - Language */
   * For any other locale, the string pointers should be different.
   */
 
+  printf("_cupsLangString(\"%s\"): ", msgid);
   msgstr = _cupsLangString(language, msgid);
   if (strcmp(language->language, "C") && msgid == msgstr)
   {
-    printf("%-8s = \"%s\" (FAIL - no message catalog loaded)\n", msgid, msgstr);
+    puts("FAIL (no message catalog loaded)");
     return (1);
   }
   else if (!strcmp(language->language, "C") && msgid != msgstr)
   {
-    printf("%-8s = \"%s\" (FAIL - POSIX locale is localized)\n", msgid, msgstr);
+    puts("FAIL (POSIX locale is localized)");
     return (1);
   }
 
-  printf("%-8s = \"%s\" (PASS)\n", msgid, msgstr);
+  printf("PASS (\"%s\")\n", msgstr);
 
   return (0);
 }
@@ -370,5 +476,7 @@ test_string(cups_lang_t *language,    /* I - Language */
 static void
 usage(void)
 {
-  puts("./testlang [-l locale] [-p ppd] [\"String to localize\"]");
+  puts("Usage: ./testlang [-l locale] [-p ppd] [\"String to localize\"]");
+  puts("");
+  puts("If no arguments are specified, all locales are tested.");
 }