1
0
mirror of https://github.com/Luzifer/repo-template.git synced 2024-09-20 17:42:58 +00:00
repo-template/vendor/github.com/google/go-github/test/fields/fields.go
2018-02-07 10:03:05 +01:00

149 lines
3.6 KiB
Go

// Copyright 2014 The go-github AUTHORS. All rights reserved.
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// This tool tests for the JSON mappings in the go-github data types. It will
// identify fields that are returned by the live GitHub API, but that are not
// currently mapped into a struct field of the relevant go-github type. This
// helps to ensure that all relevant data returned by the API is being made
// accessible, particularly new fields that are periodically (and sometimes
// quietly) added to the API over time.
//
// These tests simply aid in identifying which fields aren't being mapped; it
// is not necessarily true that every one of them should always be mapped.
// Some fields may be undocumented for a reason, either because they aren't
// actually used yet or should not be relied upon.
package main
import (
"context"
"encoding/json"
"flag"
"fmt"
"os"
"reflect"
"strings"
"github.com/google/go-github/github"
"golang.org/x/oauth2"
)
var (
client *github.Client
// auth indicates whether tests are being run with an OAuth token.
// Tests can use this flag to skip certain tests when run without auth.
auth bool
skipURLs = flag.Bool("skip_urls", false, "skip url fields")
)
func main() {
flag.Parse()
token := os.Getenv("GITHUB_AUTH_TOKEN")
if token == "" {
print("!!! No OAuth token. Some tests won't run. !!!\n\n")
client = github.NewClient(nil)
} else {
tc := oauth2.NewClient(context.Background(), oauth2.StaticTokenSource(
&oauth2.Token{AccessToken: token},
))
client = github.NewClient(tc)
auth = true
}
for _, tt := range []struct {
url string
typ interface{}
}{
//{"rate_limit", &github.RateLimits{}},
{"users/octocat", &github.User{}},
{"user", &github.User{}},
{"users/willnorris/keys", &[]github.Key{}},
{"orgs/google-test", &github.Organization{}},
{"repos/google/go-github", &github.Repository{}},
{"repos/google/go-github/issues/1", &github.Issue{}},
{"/gists/9257657", &github.Gist{}},
} {
err := testType(tt.url, tt.typ)
if err != nil {
fmt.Printf("error: %v\n", err)
}
}
}
// testType fetches the JSON resource at urlStr and compares its keys to the
// struct fields of typ.
func testType(urlStr string, typ interface{}) error {
slice := reflect.Indirect(reflect.ValueOf(typ)).Kind() == reflect.Slice
req, err := client.NewRequest("GET", urlStr, nil)
if err != nil {
return err
}
// start with a json.RawMessage so we can decode multiple ways below
raw := new(json.RawMessage)
_, err = client.Do(context.Background(), req, raw)
if err != nil {
return err
}
// unmarshal directly to a map
var m1 map[string]interface{}
if slice {
var s []map[string]interface{}
err = json.Unmarshal(*raw, &s)
if err != nil {
return err
}
m1 = s[0]
} else {
err = json.Unmarshal(*raw, &m1)
if err != nil {
return err
}
}
// unmarshal to typ first, then re-marshal and unmarshal to a map
err = json.Unmarshal(*raw, typ)
if err != nil {
return err
}
var byt []byte
if slice {
// use first item in slice
v := reflect.Indirect(reflect.ValueOf(typ))
byt, err = json.Marshal(v.Index(0).Interface())
if err != nil {
return err
}
} else {
byt, err = json.Marshal(typ)
if err != nil {
return err
}
}
var m2 map[string]interface{}
err = json.Unmarshal(byt, &m2)
if err != nil {
return err
}
// now compare the two maps
for k, v := range m1 {
if *skipURLs && strings.HasSuffix(k, "_url") {
continue
}
if _, ok := m2[k]; !ok {
fmt.Printf("%v missing field for key: %v (example value: %v)\n", reflect.TypeOf(typ), k, v)
}
}
return nil
}