Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

✨ Add Language struct and optimize result parsing for GHClient.ListProgrammingLanguages #1992

Merged
merged 40 commits into from Jun 10, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
f21d341
temp save 05262022
May 26, 2022
1edd76b
Merge branch 'main' into feat/897_go_fuzzer_check
May 26, 2022
2804c75
Merge branch 'ossf:main' into feat/897_go_fuzzer_check
aidenwang9867 May 26, 2022
d42b58d
Merge branch 'feat/897_go_fuzzer_check' of https://github.com/aidenwa…
May 26, 2022
091f311
finished golang fuzz func check, getLang interface to be done next week
May 27, 2022
949b6df
Merge branch 'main' into feat/897_go_fuzzer_check
May 31, 2022
3a225fa
temp save 05/31/2022
Jun 1, 2022
162de28
temp save 06/01/2022
Jun 2, 2022
a9f8fcb
Merge branch 'main' into feat/897_go_fuzzer_check
Jun 2, 2022
724e70c
Merge branch 'ossf:main' into feat/897_go_fuzzer_check
aidenwang9867 Jun 2, 2022
1c1c25a
Merge branch 'feat/897_go_fuzzer_check' of https://github.com/aidenwa…
Jun 2, 2022
69b807b
temp save-2 06/01/2022
Jun 2, 2022
000d9c3
temp save-1 06032022
Jun 2, 2022
f62dc64
temp save-2 06022022
Jun 2, 2022
4b0178d
temp save
Jun 3, 2022
69f6b18
temp save 06032022
Jun 3, 2022
ffe1bf1
temp save 06032022 (2)
Jun 3, 2022
739de16
update err def
Jun 3, 2022
06a0373
temp save 3
Jun 3, 2022
f999d7c
update docs for fuzzing
Jun 6, 2022
3d10b94
update docs for fuzzing
Jun 6, 2022
f481803
update checks.yaml to gen docs
Jun 6, 2022
531b103
Merge branch 'main' into feat/897_go_fuzzer_check
aidenwang9867 Jun 6, 2022
68a6cb2
temp save 0606
Jun 6, 2022
06e46ac
Merge branch 'feat/897_go_fuzzer_check' of https://github.com/aidenwa…
Jun 6, 2022
40ad2a0
temp save-2 0606
Jun 7, 2022
a918025
temp save-3 0606
Jun 7, 2022
b41e82f
temp save-4 0606
Jun 7, 2022
543ff10
fix linter errors
Jun 7, 2022
56d7d3e
fix linter errs-2
Jun 7, 2022
e043558
Merge branch 'main' into feat/897_go_fuzzer_check
aidenwang9867 Jun 7, 2022
ff02e79
fix e2e errors
Jun 7, 2022
a2a61f0
Merge branch 'feat/897_go_fuzzer_check' of https://github.com/aidenwa…
Jun 7, 2022
20b192d
0608
Jun 8, 2022
658059f
Merge branch 'ossf:main' into feat/897_go_fuzzer_check
aidenwang9867 Jun 8, 2022
af0c157
0608-2
Jun 8, 2022
5a3960e
optimize Language struct & parsing
Jun 9, 2022
3f8b765
resolved conflicts
Jun 9, 2022
f6d1c35
add more lang const
Jun 9, 2022
51764d1
resolved nits
Jun 9, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
35 changes: 25 additions & 10 deletions checks/fuzzing_test.go
Expand Up @@ -34,7 +34,7 @@ func TestFuzzing(t *testing.T) {
tests := []struct {
name string
want checker.CheckResult
langs map[clients.Language]int
langs []clients.Language
response clients.SearchResponse
wantErr bool
wantFuzzErr bool
Expand All @@ -45,8 +45,11 @@ func TestFuzzing(t *testing.T) {
{
name: "empty response",
response: clients.SearchResponse{},
langs: map[clients.Language]int{
clients.Go: 300,
langs: []clients.Language{
{
Name: clients.Go,
NumLines: 300,
},
},
wantErr: false,
},
Expand All @@ -55,9 +58,15 @@ func TestFuzzing(t *testing.T) {
response: clients.SearchResponse{
Hits: 1,
},
langs: map[clients.Language]int{
clients.Go: 100,
clients.Java: 70,
langs: []clients.Language{
{
Name: clients.Go,
NumLines: 100,
},
{
Name: clients.Java,
NumLines: 70,
},
},
wantErr: false,
want: checker.CheckResult{Score: 10},
Expand All @@ -70,8 +79,11 @@ func TestFuzzing(t *testing.T) {
},
{
name: "nil response",
langs: map[clients.Language]int{
clients.Python: 256,
langs: []clients.Language{
{
Name: clients.Python,
NumLines: 256,
},
},
wantErr: true,
want: checker.CheckResult{Score: -1},
Expand All @@ -85,8 +97,11 @@ func TestFuzzing(t *testing.T) {
},
{
name: "min score since lang not supported",
langs: map[clients.Language]int{
clients.Language("not_supported_lang"): 1490,
langs: []clients.Language{
{
Name: clients.LanguageName("a_not_supported_lang"),
NumLines: 500,
},
},
wantFuzzErr: false,
want: checker.CheckResult{Score: 0},
Expand Down
22 changes: 11 additions & 11 deletions checks/raw/fuzzing.go
Expand Up @@ -47,7 +47,7 @@ type languageFuzzConfig struct {

// Contains fuzzing speficications for programming languages.
// Please use the type Language defined in clients/languages.go rather than a raw string.
var languageFuzzSpecs = map[clients.Language]languageFuzzConfig{
var languageFuzzSpecs = map[clients.LanguageName]languageFuzzConfig{
// Default fuzz patterns for Go.
clients.Go: {
filePattern: "*_test.go",
Expand Down Expand Up @@ -93,11 +93,11 @@ func Fuzzing(c *checker.CheckRequest) (checker.FuzzingData, error) {
)
}

langMap, err := c.RepoClient.ListProgrammingLanguages()
langs, err := c.RepoClient.ListProgrammingLanguages()
if err != nil {
return checker.FuzzingData{}, fmt.Errorf("cannot get langs of repo: %w", err)
}
prominentLangs := getProminentLanguages(langMap)
prominentLangs := getProminentLanguages(langs)

for _, lang := range prominentLangs {
usingFuzzFunc, files, e := checkFuzzFunc(c, lang)
Expand Down Expand Up @@ -151,7 +151,7 @@ func checkOSSFuzz(c *checker.CheckRequest) (bool, error) {
return result.Hits > 0, nil
}

func checkFuzzFunc(c *checker.CheckRequest, lang clients.Language) (bool, []checker.File, error) {
func checkFuzzFunc(c *checker.CheckRequest, lang clients.LanguageName) (bool, []checker.File, error) {
if c.RepoClient == nil {
return false, nil, nil
}
Expand Down Expand Up @@ -217,24 +217,24 @@ var getFuzzFunc fileparser.DoWhileTrueOnFileContent = func(
return true, nil
}

func getProminentLanguages(langs map[clients.Language]int) []clients.Language {
func getProminentLanguages(langs []clients.Language) []clients.LanguageName {
numLangs := len(langs)
if numLangs == 0 {
return nil
}
totalLoC := 0
for _, LoC := range langs {
totalLoC += LoC
for _, l := range langs {
totalLoC += l.NumLines
}
// Var avgLoC calculates the average lines of code in the current repo,
// and it can stay as an int, no need for a float value.
avgLoC := totalLoC / numLangs

// Languages that have lines of code above average will be considered prominent.
ret := []clients.Language{}
for lang, LoC := range langs {
if LoC >= avgLoC {
lang = clients.Language(strings.ToLower(string(lang)))
ret := []clients.LanguageName{}
for _, l := range langs {
if l.NumLines >= avgLoC {
lang := clients.LanguageName(strings.ToLower(string(l.Name)))
ret = append(ret, lang)
}
}
Expand Down
23 changes: 13 additions & 10 deletions checks/raw/fuzzing_test.go
Expand Up @@ -165,7 +165,7 @@ func Test_fuzzFileAndFuncMatchPattern(t *testing.T) {
name string
expectedFileMatch bool
expectedFuncMatch bool
lang clients.Language
lang clients.LanguageName
fileName string
fileContent string
wantErr bool
Expand All @@ -174,7 +174,7 @@ func Test_fuzzFileAndFuncMatchPattern(t *testing.T) {
name: "Test_fuzzFuncRegex file success & func success",
expectedFileMatch: true,
expectedFuncMatch: true,
lang: "go",
lang: clients.LanguageName("go"),
fileName: "FOOoo_fOOff_BaRRR_test.go",
fileContent: `func FuzzSomething (fOo_bAR_1234 *testing.F)`,
wantErr: false,
Expand All @@ -183,7 +183,7 @@ func Test_fuzzFileAndFuncMatchPattern(t *testing.T) {
name: "Test_fuzzFuncRegex file success & func failure",
expectedFileMatch: true,
expectedFuncMatch: false,
lang: "go",
lang: clients.LanguageName("go"),
fileName: "a_unit_test.go",
fileContent: `func TestSomethingUnitTest (t *testing.T)`,
wantErr: true,
Expand All @@ -192,7 +192,7 @@ func Test_fuzzFileAndFuncMatchPattern(t *testing.T) {
name: "Test_fuzzFuncRegex file failure & func failure",
expectedFileMatch: false,
expectedFuncMatch: false,
lang: "go",
lang: clients.LanguageName("go"),
fileName: "not_a_fuzz_test_file.go",
fileContent: `func main (t *testing.T)`,
wantErr: true,
Expand All @@ -201,7 +201,7 @@ func Test_fuzzFileAndFuncMatchPattern(t *testing.T) {
name: "Test_fuzzFuncRegex not a support language",
expectedFileMatch: false,
expectedFuncMatch: false,
lang: "not_a_supported_one",
lang: clients.LanguageName("not_a_supported_one"),
fileName: "a_fuzz_test.py",
fileContent: `def NotSupported (foo)`,
wantErr: true,
Expand Down Expand Up @@ -237,7 +237,7 @@ func Test_checkFuzzFunc(t *testing.T) {
name string
want bool
wantErr bool
langs map[clients.Language]int
langs []clients.Language
fileName []string
fileContent string
}{
Expand All @@ -250,8 +250,11 @@ func Test_checkFuzzFunc(t *testing.T) {
"foo_test.go",
"main.go",
},
langs: map[clients.Language]int{
clients.Go: 100,
langs: []clients.Language{
{
Name: clients.Go,
NumLines: 100,
},
},
fileContent: "func TestFoo (t *testing.T)",
},
Expand All @@ -274,8 +277,8 @@ func Test_checkFuzzFunc(t *testing.T) {
req := checker.CheckRequest{
RepoClient: mockClient,
}
for l := range tt.langs {
got, _, err := checkFuzzFunc(&req, l)
for _, l := range tt.langs {
got, _, err := checkFuzzFunc(&req, l.Name)
if (got != tt.want || err != nil) && !tt.wantErr {
t.Errorf("checkFuzzFunc() = %v, want %v for %v", got, tt.want, tt.name)
}
Expand Down
2 changes: 1 addition & 1 deletion clients/githubrepo/client.go
Expand Up @@ -181,7 +181,7 @@ func (client *Client) ListStatuses(ref string) ([]clients.Status, error) {
}

//ListProgrammingLanguages implements RepoClient.ListProgrammingLanguages.
func (client *Client) ListProgrammingLanguages() (map[clients.Language]int, error) {
func (client *Client) ListProgrammingLanguages() ([]clients.Language, error) {
return client.languages.listProgrammingLanguages()
}

Expand Down
23 changes: 18 additions & 5 deletions clients/githubrepo/languages.go
Expand Up @@ -31,7 +31,7 @@ type languagesHandler struct {
ctx context.Context
errSetup error
repourl *repoURL
languages map[clients.Language]int
languages []clients.Language
}

func (handler *languagesHandler) init(ctx context.Context, repourl *repoURL) {
Expand All @@ -52,21 +52,34 @@ func (handler *languagesHandler) setup() error {
handler.errSetup = fmt.Errorf("request for repo languages failed with %w", err)
return
}
handler.languages = map[clients.Language]int{}
// The client.repoClient.Do API writes the reponse body to the handler.languages,
bodyJSON := map[clients.LanguageName]int{}
// The client.repoClient.Do API writes the reponse body to var bodyJSON,
// so we can ignore the first returned variable (the entire http response object)
// since we only need the response body here.
_, err = client.Do(handler.ctx, req, &handler.languages)
_, err = client.Do(handler.ctx, req, &bodyJSON)
if err != nil {
handler.errSetup = fmt.Errorf("response for repo languages failed with %w", err)
return
}
// Parse the raw JSON to an array of languages.
for k, v := range bodyJSON {
// TODO: once the const defined in clients/languages.go becomes a complete list of langs supported,
// add support here so that for not supported langs, it emits an "not-supported" error and break the parse.
// Currently, we are parsing all the JSON-returned langs into the result since the const is incomplete.
handler.languages = append(handler.languages,
clients.Language{
Name: k,
NumLines: v,
},
)
}
handler.errSetup = nil
})

return handler.errSetup
}

func (handler *languagesHandler) listProgrammingLanguages() (map[clients.Language]int, error) {
func (handler *languagesHandler) listProgrammingLanguages() ([]clients.Language, error) {
if err := handler.setup(); err != nil {
return nil, fmt.Errorf("error during languagesHandler.setup: %w", err)
}
Expand Down
65 changes: 42 additions & 23 deletions clients/languages.go
Expand Up @@ -14,60 +14,79 @@

package clients

// Language represents a customized string for languages used by clients.
// A language could be a programming language, or more general,
// such as Dockerfile, CMake, HTML, YAML, etc.
type Language string
// LanguageName is the name of a language, a customized type of string.
type LanguageName string

// TODO: retrieve all languages supported by GitHub.
// TODO: retrieve all languages supported by GitHub, or add one manually if needed.
// Currently, this is still an incomplete list of languages.
const (
// Go: https://go.dev/
Go Language = "go"
Go LanguageName = "go"

// Python: https://www.python.org/
Python Language = "python"
Python LanguageName = "python"

// JavaScript: https://www.javascript.com/
JavaScript Language = "javascript"
JavaScript LanguageName = "javascript"

// C++: https://cplusplus.com/
Cpp Language = "c++"
Cpp LanguageName = "c++"

// C: https://www.open-std.org/jtc1/sc22/wg14/
C Language = "c"
C LanguageName = "c"

// TypeScript: https://www.typescriptlang.org/
TypeScript Language = "typescript"
TypeScript LanguageName = "typescript"

// Java: https://www.java.com/en/
Java Language = "java"
Java LanguageName = "java"

// C#: https://docs.microsoft.com/en-us/dotnet/csharp/
CSharp Language = "c#"
CSharp LanguageName = "c#"

// Ruby: https://www.ruby-lang.org/
Ruby Language = "ruby"
Ruby LanguageName = "ruby"

// PHP: https://www.php.net/
PHP Language = "php"
PHP LanguageName = "php"

// Starlark: https://github.com/bazelbuild/starlark
StarLark Language = "starlark"
StarLark LanguageName = "starlark"

// Scala: https://www.scala-lang.org/
Scala Language = "scala"
Scala LanguageName = "scala"

// Kotlin: https://kotlinlang.org/
Kotlin Language = "kotlin"
Kotlin LanguageName = "kotlin"

// Swift: https://github.com/apple/swift
Swift Language = "swift"
Swift LanguageName = "swift"

// Rust: https://github.com/rust-lang/rust
Rust Language = "rust"
Rust LanguageName = "rust"

// CMake: https://cmake.org/
CMake LanguageName = "cmake"

// Other indicates other programming languages not listed by the GitHub API.
Other Language = "other"
// Dockerfile: https://docs.docker.com/engine/reference/builder/
Dockerfile LanguageName = "dockerfile"

// Add more programming languages here if needed, please use lower cases.
// Other indicates other languages not listed by the GitHub API.
Other LanguageName = "other"

// Add more languages here if needed,
// please use lowercases for the LanguageName value.
)

// Language represents a customized struct for languages used by clients.
// A language could be a programming language, or more general,
// such as Dockerfile, CMake, HTML, YAML, etc.
type Language struct {
// Name is the name of this language.
Name LanguageName

// NumLines is the total number of code lines of this language in the repo.
NumLines int

// TODO: add more properties for Language.
}
2 changes: 1 addition & 1 deletion clients/localdir/client.go
Expand Up @@ -220,7 +220,7 @@ func (client *localDirClient) Close() error {

// ListProgrammingLanguages implements RepoClient.ListProgrammingLanguages.
// TODO: add ListProgrammingLanguages support for local directories
func (client *localDirClient) ListProgrammingLanguages() (map[clients.Language]int, error) {
func (client *localDirClient) ListProgrammingLanguages() ([]clients.Language, error) {
return nil, fmt.Errorf("ListProgrammingLanguages: %w", clients.ErrUnsupportedFeature)
}

Expand Down
4 changes: 2 additions & 2 deletions clients/mockclients/repo_client.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.