vitess.io/vitess@v0.16.2/go/mysql/collations/golden_test.go (about)

     1  /*
     2  Copyright 2021 The Vitess Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package collations
    18  
    19  import (
    20  	"bytes"
    21  	"fmt"
    22  	"os"
    23  	"path/filepath"
    24  	"sort"
    25  	"strings"
    26  	"testing"
    27  
    28  	"github.com/stretchr/testify/assert"
    29  	"github.com/stretchr/testify/require"
    30  
    31  	"vitess.io/vitess/go/mysql/collations/internal/charset"
    32  	"vitess.io/vitess/go/mysql/collations/internal/testutil"
    33  )
    34  
    35  func TestGoldenWeights(t *testing.T) {
    36  	gllGoldenTests, err := filepath.Glob("testdata/wiki_*.gob.gz")
    37  	if err != nil {
    38  		t.Fatal(err)
    39  	}
    40  
    41  	for _, goldenPath := range gllGoldenTests {
    42  		golden := &testutil.GoldenTest{}
    43  		if err := golden.DecodeFromFile(goldenPath); err != nil {
    44  			t.Fatal(err)
    45  		}
    46  
    47  		for _, goldenCase := range golden.Cases {
    48  			t.Run(fmt.Sprintf("%s (%s)", golden.Name, goldenCase.Lang), func(t *testing.T) {
    49  				for coll, expected := range goldenCase.Weights {
    50  					coll := testcollation(t, coll)
    51  
    52  					input, err := charset.ConvertFromUTF8(nil, coll.Charset(), goldenCase.Text)
    53  					if err != nil {
    54  						t.Fatal(err)
    55  					}
    56  
    57  					result := coll.WeightString(nil, input, 0)
    58  					assert.True(t, bytes.Equal(expected, result), "mismatch for collation=%s\noriginal: %s\ninput:    %#v\nexpected: %v\nactual:   %v", coll.Name(), string(goldenCase.Text), input, expected, result)
    59  
    60  				}
    61  			})
    62  		}
    63  	}
    64  }
    65  
    66  func TestCollationsForLanguage(t *testing.T) {
    67  	allCollations := testall()
    68  	langCounts := make(map[testutil.Lang][]string)
    69  
    70  	for lang := range testutil.KnownLanguages {
    71  		var matched []string
    72  		for _, coll := range allCollations {
    73  			name := coll.Name()
    74  			if lang.MatchesCollation(name) {
    75  				matched = append(matched, name)
    76  			}
    77  		}
    78  		langCounts[lang] = matched
    79  	}
    80  
    81  	for lang := range testutil.KnownLanguages {
    82  		assert.NotEqual(t, 0, len(langCounts[lang]), "no collations found for %q", lang)
    83  
    84  		t.Logf("%s: %v", lang, langCounts[lang])
    85  	}
    86  }
    87  
    88  // XTestSupportTables should not run by default; it is used to generate a Markdown
    89  // table with Collation support information for the current build of Vitess.
    90  func XTestSupportTables(t *testing.T) {
    91  	var versions = []collver{
    92  		collverMySQL80,
    93  		collverMySQL57,
    94  		collverMySQL56,
    95  		collverMariaDB103,
    96  		collverMariaDB102,
    97  		collverMariaDB101,
    98  		collverMariaDB100,
    99  	}
   100  
   101  	var envs []*Environment
   102  	for _, v := range versions {
   103  		envs = append(envs, makeEnv(v))
   104  	}
   105  
   106  	var all []ID
   107  	for id := range globalVersionInfo {
   108  		all = append(all, id)
   109  	}
   110  	sort.Slice(all, func(i, j int) bool {
   111  		return all[i] < all[j]
   112  	})
   113  
   114  	var out = os.Stdout
   115  
   116  	fmt.Fprintf(out, "| Collation | Charset")
   117  	for _, env := range envs {
   118  		fmt.Fprintf(out, " | %s", env.version.String())
   119  	}
   120  	fmt.Fprintf(out, " |\n|%s\n", strings.Repeat("---|", len(envs)+2))
   121  
   122  	for _, id := range all {
   123  		coll := globalAllCollations[id]
   124  		if coll == nil {
   125  			vdata := globalVersionInfo[id]
   126  
   127  			var collnames []string
   128  			for _, alias := range vdata.alias {
   129  				collnames = append(collnames, alias.name)
   130  				break
   131  			}
   132  			collname := strings.Join(collnames, ",")
   133  			parts := strings.Split(collname, "_")
   134  
   135  			fmt.Fprintf(out, "| %s | %s", collname, parts[0])
   136  			for _, env := range envs {
   137  				var supported bool
   138  				for _, alias := range vdata.alias {
   139  					if alias.mask&env.version != 0 {
   140  						supported = true
   141  						break
   142  					}
   143  				}
   144  				if supported {
   145  					fmt.Fprintf(out, " | ⚠️")
   146  				} else {
   147  					fmt.Fprintf(out, " | ❌")
   148  				}
   149  			}
   150  		} else {
   151  			fmt.Fprintf(out, "| %s | %s", coll.Name(), coll.Charset().Name())
   152  			for _, env := range envs {
   153  				_, supported := env.byID[coll.ID()]
   154  				if supported {
   155  					fmt.Fprintf(out, " | ✅")
   156  				} else {
   157  					fmt.Fprintf(out, " | ❌")
   158  				}
   159  			}
   160  		}
   161  
   162  		fmt.Fprintf(out, " |\n")
   163  	}
   164  }
   165  
   166  func TestAllCollationsByCharset(t *testing.T) {
   167  	var defaults1 = map[string][2]string{
   168  		"utf8mb4": {"utf8mb4_general_ci", "utf8mb4_bin"},
   169  	}
   170  	var defaults2 = map[string][2]string{
   171  		"utf8mb4": {"utf8mb4_0900_ai_ci", "utf8mb4_0900_bin"},
   172  	}
   173  
   174  	for _, tc := range []struct {
   175  		version  collver
   176  		defaults map[string][2]string
   177  	}{
   178  		{collverMariaDB100, defaults1},
   179  		{collverMariaDB101, defaults1},
   180  		{collverMariaDB102, defaults1},
   181  		{collverMariaDB103, defaults1},
   182  		{collverMySQL56, defaults1},
   183  		{collverMySQL57, defaults1},
   184  		{collverMySQL80, defaults2},
   185  	} {
   186  		t.Run(tc.version.String(), func(t *testing.T) {
   187  			env := makeEnv(tc.version)
   188  			for csname, cset := range env.byCharset {
   189  				switch csname {
   190  				case "gb18030":
   191  					// this doesn't work yet
   192  					continue
   193  				}
   194  				require.NotNil(t, cset.Default, "charset %s has no default", csname)
   195  				require.NotNil(t, cset.Binary, "charset %s has no binary", csname)
   196  
   197  			}
   198  
   199  			for charset, expected := range tc.defaults {
   200  				expectedDefault, expectedBinary := expected[0], expected[1]
   201  				if def := env.DefaultCollationForCharset(charset); def.Name() != expectedDefault {
   202  					t.Fatalf("bad default for utf8mb4: %s (expected %s)", def.Name(), expectedDefault)
   203  				}
   204  				if def := env.BinaryCollationForCharset(charset); def.Name() != expectedBinary {
   205  					t.Fatalf("bad binary for utf8mb4: %s (expected %s)", def.Name(), expectedBinary)
   206  				}
   207  			}
   208  		})
   209  	}
   210  }