(root)/
fontconfig-2.14.2/
test/
test-family-matching.c
       1  /*
       2   * fontconfig/test/test-family-matching.c
       3   *
       4   * Copyright © 2020 Zoltan Vandrus
       5   *
       6   * Permission to use, copy, modify, distribute, and sell this software and its
       7   * documentation for any purpose is hereby granted without fee, provided that
       8   * the above copyright notice appear in all copies and that both that
       9   * copyright notice and this permission notice appear in supporting
      10   * documentation, and that the name of the author(s) not be used in
      11   * advertising or publicity pertaining to distribution of the software without
      12   * specific, written prior permission.  The authors make no
      13   * representations about the suitability of this software for any purpose.  It
      14   * is provided "as is" without express or implied warranty.
      15   *
      16   * THE AUTHOR(S) DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
      17   * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
      18   * EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY SPECIAL, INDIRECT OR
      19   * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
      20   * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
      21   * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
      22   * PERFORMANCE OF THIS SOFTWARE.
      23   */
      24  #include <stdio.h>
      25  #include <stdlib.h>
      26  #include <fontconfig/fontconfig.h>
      27  
      28  #define FC_TEST_RESULT "testresult"
      29  
      30  typedef enum _TestMatchResult {
      31      TestMatch,
      32      TestNoMatch,
      33      TestMatchError
      34  } TestMatchResult;
      35  
      36  typedef enum _TestResult {
      37      TestPassed,
      38      TestFailed,
      39      TestError
      40  } TestResult;
      41  
      42  static TestMatchResult
      43  TestMatchPattern (const char *test, FcPattern *p)
      44  {
      45      const FcChar8 *xml_pre = (const FcChar8 *) ""
      46          "<fontconfig>\n"
      47          "  <match>\n"
      48          "";
      49  
      50      const FcChar8 *xml_post = (const FcChar8 *) ""
      51          "    <edit name=\""FC_TEST_RESULT"\">\n"
      52          "      <bool>true</bool>\n"
      53          "    </edit>\n"
      54          "  </match>\n"
      55          "</fontconfig>\n"
      56          "";
      57  
      58      FcPattern *pat = NULL;
      59      FcChar8 *concat = NULL;
      60      FcChar8 *xml = NULL;
      61      FcConfig *cfg = NULL;
      62      FcResult result;
      63      FcBool dummy;
      64      TestMatchResult ret = TestMatchError;
      65  
      66      pat = FcPatternDuplicate (p);
      67      if (!pat)
      68      {
      69          fprintf (stderr, "Unable to duplicate pattern.\n");
      70          goto bail;
      71      }
      72  
      73      concat = FcStrPlus (xml_pre, (const FcChar8 *) test);
      74      if (!concat)
      75      {
      76          fprintf (stderr, "Concatenation failed.\n");
      77          goto bail;
      78      }
      79  
      80      xml = FcStrPlus (concat, xml_post);
      81      if (!xml)
      82      {
      83          fprintf (stderr, "Concatenation failed.\n");
      84          goto bail;
      85      }
      86  
      87      cfg = FcConfigCreate ();
      88      if (!cfg)
      89      {
      90          fprintf (stderr, "Unable to create a new empty config.\n");
      91          goto bail;
      92      }
      93  
      94      if (!FcConfigParseAndLoadFromMemory (cfg, xml, FcTrue))
      95      {
      96          fprintf (stderr, "Unable to load a config from memory.\n");
      97          goto bail;
      98      }
      99  
     100      if (!FcConfigSubstitute (cfg, pat, FcMatchPattern))
     101      {
     102          fprintf (stderr, "Unable to substitute config.\n");
     103          goto bail;
     104      }
     105  
     106      result = FcPatternGetBool (pat, FC_TEST_RESULT, 0, &dummy);
     107      switch (result) {
     108      case FcResultMatch:
     109          ret = TestMatch;
     110          break;
     111      case FcResultNoMatch:
     112          ret = TestNoMatch;
     113          break;
     114      default:
     115          fprintf (stderr, "Unable to check pattern.\n");
     116          break;
     117      }
     118  
     119  bail:
     120      if (cfg)
     121  	FcConfigDestroy (cfg);
     122      if (xml)
     123  	FcStrFree (xml);
     124      if (concat)
     125  	FcStrFree (concat);
     126      if (pat)
     127  	FcPatternDestroy (pat);
     128      return ret;
     129  }
     130  
     131  static TestResult
     132  TestShouldMatchPattern(const char* test, FcPattern *pat, int negate)
     133  {
     134      switch (TestMatchPattern (test, pat)) {
     135      case TestMatch:
     136          if (!negate) {
     137              return TestPassed;
     138          }
     139          else
     140          {
     141              printf ("Following test unexpectedly matched:\n%s", test);
     142              printf ("on\n");
     143              FcPatternPrint (pat);
     144              return TestFailed;
     145          }
     146          break;
     147      case TestNoMatch:
     148          if (!negate) {
     149              printf ("Following test should have matched:\n%s", test);
     150              printf ("on\n");
     151              FcPatternPrint (pat);
     152              return TestFailed;
     153          }
     154          else
     155          {
     156              return TestPassed;
     157          }
     158          break;
     159      case TestMatchError:
     160          return TestError;
     161          break;
     162      default:
     163          fprintf (stderr, "This shouldn't have been reached.\n");
     164          return TestError;
     165      }
     166  }
     167  
     168  #define MAX(a,b) ((a) > (b) ? (a) : (b))
     169  
     170  static TestResult
     171  UpdateResult (TestResult* res, TestResult resNew)
     172  {
     173      *res = MAX(*res, resNew);
     174      return *res;
     175  }
     176  
     177  static TestResult
     178  TestFamily (void)
     179  {
     180      const char *test;
     181      TestResult res = TestPassed;
     182  
     183      FcPattern *pat = FcPatternBuild (NULL,
     184          FC_FAMILY, FcTypeString, "family1",
     185          FC_FAMILY, FcTypeString, "family2",
     186          FC_FAMILY, FcTypeString, "family3",
     187          NULL);
     188  
     189      if (!pat)
     190      {
     191          fprintf (stderr, "Unable to build pattern.\n");
     192          return TestError;
     193      }
     194  
     195      #define SHOULD_MATCH(p,t) \
     196          UpdateResult (&res, TestShouldMatchPattern (t, p, 0))
     197      #define SHOULD_NOT_MATCH(p,t) \
     198          UpdateResult (&res, TestShouldMatchPattern (t, p, 1))
     199  
     200      test = "<test qual=\"all\" name=\"family\" compare=\"not_eq\">\n"
     201             "    <string>foo</string>\n"
     202             "</test>\n"
     203             "";
     204      SHOULD_MATCH(pat, test);
     205  
     206      test = ""
     207             "<test qual=\"all\" name=\"family\" compare=\"not_eq\">\n"
     208             "    <string>family2</string>\n"
     209             "</test>\n"
     210             "";
     211      SHOULD_NOT_MATCH(pat, test);
     212  
     213      test = ""
     214             "<test qual=\"any\" name=\"family\" compare=\"eq\">\n"
     215             "    <string>family3</string>\n"
     216             "</test>\n"
     217             "";
     218      SHOULD_MATCH(pat, test);
     219  
     220      test = ""
     221             "<test qual=\"any\" name=\"family\" compare=\"eq\">\n"
     222             "    <string>foo</string>\n"
     223             "</test>\n"
     224             "";
     225      SHOULD_NOT_MATCH(pat, test);
     226  
     227      FcPatternDestroy (pat);
     228      return res;
     229  }
     230  
     231  int
     232  main (void)
     233  {
     234      return (TestFamily ());
     235  }