code.gitea.io/gitea@v1.22.3/tests/integration/linguist_test.go (about) 1 // Copyright 2024 The Gitea Authors. All rights reserved. 2 // SPDX-License-Identifier: MIT 3 4 package integration 5 6 import ( 7 "context" 8 "net/url" 9 "strings" 10 "testing" 11 "time" 12 13 "code.gitea.io/gitea/models/db" 14 repo_model "code.gitea.io/gitea/models/repo" 15 "code.gitea.io/gitea/models/unittest" 16 user_model "code.gitea.io/gitea/models/user" 17 "code.gitea.io/gitea/modules/git" 18 "code.gitea.io/gitea/modules/indexer/stats" 19 "code.gitea.io/gitea/modules/queue" 20 repo_service "code.gitea.io/gitea/services/repository" 21 files_service "code.gitea.io/gitea/services/repository/files" 22 23 "github.com/stretchr/testify/assert" 24 ) 25 26 func TestLinguist(t *testing.T) { 27 onGiteaRun(t, func(t *testing.T, _ *url.URL) { 28 user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}) 29 30 cppContent := "#include <iostream>\nint main() {\nstd::cout << \"Hello Gitea!\";\nreturn 0;\n}" 31 pyContent := "print(\"Hello Gitea!\")" 32 phpContent := "<?php\necho 'Hallo Welt';\n?>" 33 lockContent := "# This file is automatically @generated by Poetry 1.7.1 and should not be changed by hand." 34 mdContent := "markdown" 35 36 cases := []struct { 37 GitAttributesContent string 38 FilesToAdd []*files_service.ChangeRepoFile 39 ExpectedLanguageOrder []string 40 }{ 41 // case 0 42 { 43 ExpectedLanguageOrder: []string{}, 44 }, 45 // case 1 46 { 47 FilesToAdd: []*files_service.ChangeRepoFile{ 48 { 49 TreePath: "cplusplus.cpp", 50 ContentReader: strings.NewReader(cppContent), 51 }, 52 { 53 TreePath: "python.py", 54 ContentReader: strings.NewReader(pyContent), 55 }, 56 { 57 TreePath: "php.php", 58 ContentReader: strings.NewReader(phpContent), 59 }, 60 }, 61 ExpectedLanguageOrder: []string{"C++", "PHP", "Python"}, 62 }, 63 // case 2 64 { 65 FilesToAdd: []*files_service.ChangeRepoFile{ 66 { 67 TreePath: ".cplusplus.cpp", 68 ContentReader: strings.NewReader(cppContent), 69 }, 70 { 71 TreePath: "python.py", 72 ContentReader: strings.NewReader(pyContent), 73 }, 74 { 75 TreePath: "vendor/php.php", 76 ContentReader: strings.NewReader(phpContent), 77 }, 78 }, 79 ExpectedLanguageOrder: []string{"Python"}, 80 }, 81 // case 3 82 { 83 GitAttributesContent: "*.cpp linguist-language=Go", 84 FilesToAdd: []*files_service.ChangeRepoFile{ 85 { 86 TreePath: "cplusplus.cpp", 87 ContentReader: strings.NewReader(cppContent), 88 }, 89 }, 90 ExpectedLanguageOrder: []string{"Go"}, 91 }, 92 // case 4 93 { 94 GitAttributesContent: "*.cpp gitlab-language=Go?parent=json", 95 FilesToAdd: []*files_service.ChangeRepoFile{ 96 { 97 TreePath: "cplusplus.cpp", 98 ContentReader: strings.NewReader(cppContent), 99 }, 100 }, 101 ExpectedLanguageOrder: []string{"Go"}, 102 }, 103 // case 5 104 { 105 GitAttributesContent: "*.cpp linguist-language=HTML gitlab-language=Go?parent=json", 106 FilesToAdd: []*files_service.ChangeRepoFile{ 107 { 108 TreePath: "cplusplus.cpp", 109 ContentReader: strings.NewReader(cppContent), 110 }, 111 }, 112 ExpectedLanguageOrder: []string{"HTML"}, 113 }, 114 // case 6 115 { 116 GitAttributesContent: "vendor/** linguist-vendored=false", 117 FilesToAdd: []*files_service.ChangeRepoFile{ 118 { 119 TreePath: "vendor/php.php", 120 ContentReader: strings.NewReader(phpContent), 121 }, 122 }, 123 ExpectedLanguageOrder: []string{"PHP"}, 124 }, 125 // case 7 126 { 127 GitAttributesContent: "*.cpp linguist-vendored=true\n*.py linguist-vendored\nvendor/** -linguist-vendored", 128 FilesToAdd: []*files_service.ChangeRepoFile{ 129 { 130 TreePath: "cplusplus.cpp", 131 ContentReader: strings.NewReader(cppContent), 132 }, 133 { 134 TreePath: "python.py", 135 ContentReader: strings.NewReader(pyContent), 136 }, 137 { 138 TreePath: "vendor/php.php", 139 ContentReader: strings.NewReader(phpContent), 140 }, 141 }, 142 ExpectedLanguageOrder: []string{"PHP"}, 143 }, 144 // case 8 145 { 146 GitAttributesContent: "poetry.lock linguist-language=Go", 147 FilesToAdd: []*files_service.ChangeRepoFile{ 148 { 149 TreePath: "poetry.lock", 150 ContentReader: strings.NewReader(lockContent), 151 }, 152 }, 153 ExpectedLanguageOrder: []string{"Go"}, 154 }, 155 // case 9 156 { 157 GitAttributesContent: "poetry.lock linguist-generated=false", 158 FilesToAdd: []*files_service.ChangeRepoFile{ 159 { 160 TreePath: "poetry.lock", 161 ContentReader: strings.NewReader(lockContent), 162 }, 163 }, 164 ExpectedLanguageOrder: []string{"TOML"}, 165 }, 166 // case 10 167 { 168 GitAttributesContent: "*.cpp -linguist-detectable", 169 FilesToAdd: []*files_service.ChangeRepoFile{ 170 { 171 TreePath: "cplusplus.cpp", 172 ContentReader: strings.NewReader(cppContent), 173 }, 174 }, 175 ExpectedLanguageOrder: []string{}, 176 }, 177 // case 11 178 { 179 GitAttributesContent: "*.md linguist-detectable", 180 FilesToAdd: []*files_service.ChangeRepoFile{ 181 { 182 TreePath: "test.md", 183 ContentReader: strings.NewReader(mdContent), 184 }, 185 }, 186 ExpectedLanguageOrder: []string{"Markdown"}, 187 }, 188 // case 12 189 { 190 GitAttributesContent: "test2.md linguist-detectable", 191 FilesToAdd: []*files_service.ChangeRepoFile{ 192 { 193 TreePath: "cplusplus.cpp", 194 ContentReader: strings.NewReader(cppContent), 195 }, 196 { 197 TreePath: "test.md", 198 ContentReader: strings.NewReader(mdContent), 199 }, 200 { 201 TreePath: "test2.md", 202 ContentReader: strings.NewReader(mdContent), 203 }, 204 }, 205 ExpectedLanguageOrder: []string{"C++", "Markdown"}, 206 }, 207 // case 13 208 { 209 GitAttributesContent: "README.md linguist-documentation=false", 210 FilesToAdd: []*files_service.ChangeRepoFile{ 211 { 212 TreePath: "README.md", 213 ContentReader: strings.NewReader(mdContent), 214 }, 215 }, 216 ExpectedLanguageOrder: []string{"Markdown"}, 217 }, 218 } 219 220 for i, c := range cases { 221 repo, err := repo_service.CreateRepository(db.DefaultContext, user, user, repo_service.CreateRepoOptions{ 222 Name: "linguist-test", 223 }) 224 assert.NoError(t, err) 225 226 files := []*files_service.ChangeRepoFile{ 227 { 228 TreePath: ".gitattributes", 229 ContentReader: strings.NewReader(c.GitAttributesContent), 230 }, 231 } 232 files = append(files, c.FilesToAdd...) 233 for _, f := range files { 234 f.Operation = "create" 235 } 236 237 _, err = files_service.ChangeRepoFiles(git.DefaultContext, repo, user, &files_service.ChangeRepoFilesOptions{ 238 Files: files, 239 OldBranch: repo.DefaultBranch, 240 NewBranch: repo.DefaultBranch, 241 }) 242 assert.NoError(t, err) 243 244 assert.NoError(t, stats.UpdateRepoIndexer(repo)) 245 assert.NoError(t, queue.GetManager().FlushAll(context.Background(), 10*time.Second)) 246 247 stats, err := repo_model.GetTopLanguageStats(db.DefaultContext, repo, len(c.FilesToAdd)) 248 assert.NoError(t, err) 249 250 languages := make([]string, 0, len(stats)) 251 for _, s := range stats { 252 languages = append(languages, s.Language) 253 } 254 assert.Equal(t, c.ExpectedLanguageOrder, languages, "case %d: unexpected language stats", i) 255 256 assert.NoError(t, repo_service.DeleteRepository(db.DefaultContext, user, repo, false)) 257 } 258 }) 259 }