diff --git a/.fossa.yml b/.fossa.yml deleted file mode 100644 index 3f07cce..0000000 --- a/.fossa.yml +++ /dev/null @@ -1,20 +0,0 @@ -# SPDX-FileCopyrightText: 2021 Open Networking Foundation -# -# SPDX-License-Identifier: Apache-2.0 -# -# Generated by FOSSA CLI (https://github.com/fossas/fossa-cli) -# Visit https://fossa.com to learn more -# -# Usage: FOSSA_API_KEY=<> fossa analyze -# -T is not supported at this moment from fossa side. -version: 2 -cli: - server: https://app.fossa.com - fetcher: custom - project: openapi -analyze: - modules: - - name: openapi - type: raw - target: ../openapi - path: ../openapi diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index fa16650..db94a91 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -25,7 +25,7 @@ jobs: - name: Build run: go build ./... - unit-tests: + lint: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 @@ -34,8 +34,11 @@ jobs: with: go-version-file: 'go.mod' - - name: Unit tests - run: go test ./... + - name: golangci-lint + uses: golangci/golangci-lint-action@v6.1.0 + with: + version: latest + args: -v --config ./.golangci.yml license-check: runs-on: ubuntu-latest @@ -54,3 +57,15 @@ jobs: uses: fossa-contrib/fossa-action@v3 with: fossa-api-key: 0c3bbcdf20e157bbd487dae173751b28 + + unit-tests: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - uses: actions/setup-go@v5 + with: + go-version-file: 'go.mod' + + - name: Unit tests + run: go test ./... diff --git a/.golangci.yml b/.golangci.yml new file mode 100644 index 0000000..ec4f6e9 --- /dev/null +++ b/.golangci.yml @@ -0,0 +1,324 @@ +# SPDX-FileCopyrightText: 2021 Open Networking Foundation +# Copyright 2019 free5GC.org +# +# SPDX-License-Identifier: Apache-2.0 +# + +# This file contains all available configuration options +# with their default values. +# options for analysis running +run: + # default concurrency is a available CPU number + concurrency: 4 + # timeout for analysis, e.g. 30s, 5m, default is 1m + timeout: 1m + # exit code when at least one issue was found, default is 1 + issues-exit-code: 1 + # include test files or not, default is true + tests: true + # list of build tags, all linters use it. Default is empty list. + build-tags: + # which dirs to skip: issues from them won't be reported; + # can use regexp here: generated.*, regexp is applied on full path; + # default value is empty list, but default dirs are skipped independently + # from this option's value (see skip-dirs-use-default). + # "/" will be replaced by current OS file path separator to properly work + # on Windows. + skip-dirs: + # default is true. Enables skipping of directories: + # vendor$, third_party$, testdata$, examples$, Godeps$, builtin$ + skip-dirs-use-default: true + # which files to skip: they will be analyzed, but issues from them + # won't be reported. Default value is empty list, but there is + # no need to include all autogenerated files, we confidently recognize + # autogenerated files. If it's not please let us know. + # "/" will be replaced by current OS file path separator to properly work + # on Windows. + skip-files: + - "api_.*\\.go$" + - "model_.*\\.go$" + - "client.go" + # by default isn't set. If set we pass it to "go list -mod={option}". From "go help modules": + # If invoked with -mod=readonly, the go command is disallowed from the implicit + # automatic updating of go.mod described above. Instead, it fails when any changes + # to go.mod are needed. This setting is most useful to check that go.mod does + # not need updates, such as in a continuous integration and testing system. + # If invoked with -mod=vendor, the go command assumes that the vendor + # directory holds the correct copies of dependencies and ignores + # the dependency descriptions in go.mod. + #modules-download-mode: readonly|release|vendor + # Allow multiple parallel golangci-lint instances running. + # If false (default) - golangci-lint acquires file lock on start. + allow-parallel-runners: true +# output configuration options +output: + # colored-line-number|line-number|json|tab|checkstyle|code-climate, default is "colored-line-number" + format: colored-line-number + # print lines of code with issue, default is true + print-issued-lines: true + # print linter name in the end of issue text, default is true + print-linter-name: true + # make issues output unique by line, default is true + uniq-by-line: true +# all available settings of specific linters +linters-settings: + errcheck: + # report about not checking of errors in type assertions: `a := b.(MyStruct)`; + # default is false: such cases aren't reported by default. + check-type-assertions: false + # report about assignment of errors to blank identifier: `num, _ := strconv.Atoi(numStr)`; + # default is false: such cases aren't reported by default. + check-blank: true + # [deprecated] comma-separated list of pairs of the form pkg:regex + # the regex is used to ignore names within pkg. (default "fmt:.*"). + # see https://github.com/kisielk/errcheck#the-deprecated-method for details + #ignore: fmt:.*,io/ioutil:^Read.* + # path to a file containing a list of functions to exclude from checking + # see https://github.com/kisielk/errcheck#excluding-functions for details + #exclude: /path/to/file.txt + funlen: + lines: 60 + statements: 40 + gocognit: + # minimal code complexity to report, 30 by default (but we recommend 10-20) + min-complexity: 10 + nestif: + # minimal complexity of if statements to report, 5 by default + min-complexity: 4 + goconst: + # minimal length of string constant, 3 by default + min-len: 3 + # minimal occurrences count to trigger, 3 by default + min-occurrences: 3 + gocritic: + # Which checks should be enabled; can't be combined with 'disabled-checks'; + # See https://go-critic.github.io/overview#checks-overview + # To check which checks are enabled run `GL_DEBUG=gocritic golangci-lint run` + # By default list of stable checks is used. + enabled-checks: + #- rangeValCopy + # Which checks should be disabled; can't be combined with 'enabled-checks'; default is empty + disabled-checks: + - regexpMust + # Enable multiple checks by tags, run `GL_DEBUG=gocritic golangci-lint run` to see all tags and checks. + # Empty list by default. See https://github.com/go-critic/go-critic#usage -> section "Tags". + enabled-tags: + - performance + disabled-tags: + - experimental + settings: # settings passed to gocritic + captLocal: # must be valid enabled check name + paramsOnly: true + rangeValCopy: + sizeThreshold: 32 + gocyclo: + # minimal code complexity to report, 30 by default (but we recommend 10-20) + min-complexity: 10 + godox: + # report any comments starting with keywords, this is useful for TODO or FIXME comments that + # might be left in the code accidentally and should be resolved before merging + keywords: # default keywords are TODO, BUG, and FIXME, these can be overwritten by this setting + #- TODO + - FIXME + - BUG + #- NOTE + #- OPTIMIZE # marks code that should be optimized before merging + #- HACK # marks hack-arounds that should be removed before merging + - XXX # Fatal! Important problem + gofmt: + # simplify code: gofmt with `-s` option, true by default + simplify: true + goimports: + # put imports beginning with prefix after 3rd-party packages; + # it's a comma-separated list of prefixes + local-prefixes: github.com/org/project + golint: + # minimal confidence for issues, default is 0.8 + min-confidence: 0.8 + gomnd: + settings: + mnd: + # the list of enabled checks, see https://github.com/tommy-muehle/go-mnd/#checks for description. + checks: argument,case,condition,operation,return,assign + gomodguard: + allowed: + modules: # List of allowed modules + # - gopkg.in/yaml.v2 + domains: # List of allowed module domains + # - golang.org + blocked: + modules: # List of blocked modules + # - github.com/uudashr/go-module: # Blocked module + # recommendations: # Recommended modules that should be used instead (Optional) + # - golang.org/x/mod + # reason: "`mod` is the official go.mod parser library." # Reason why the recommended module should be used (Optional) + versions: # List of blocked module version constraints + # - github.com/mitchellh/go-homedir: # Blocked module with version constraint + # version: "< 1.1.0" # Version constraint, see https://github.com/Masterminds/semver#basic-comparisons + # reason: "testing if blocked version constraint works." # Reason why the version constraint exists. (Optional) + govet: + # report about shadowed variables + check-shadowing: true + # settings per analyzer + settings: + printf: # analyzer name, run `go tool vet help` to see all analyzers + funcs: # run `go tool vet help printf` to see available settings for `printf` analyzer + - (github.com/golangci/golangci-lint/pkg/logutils.Log).Infof + - (github.com/golangci/golangci-lint/pkg/logutils.Log).Warnf + - (github.com/golangci/golangci-lint/pkg/logutils.Log).Errorf + - (github.com/golangci/golangci-lint/pkg/logutils.Log).Fatalf + # enable all analyzers + enable-all: true + disable: + - fieldalignment + disable-all: false + depguard: + list-type: blacklist + include-go-root: false + packages: + - github.com/sirupsen/logrus + packages-with-error-message: + # specify an error message to output when a blacklisted package is used + - github.com/sirupsen/logrus: "logging is allowed only by logutils.Log" + lll: + # max line length, lines longer will be reported. Default is 120. + # '\t' is counted as 1 character by default, and can be changed with the tab-width option + line-length: 120 + # tab width in spaces. Default to 1. + tab-width: 1 + maligned: + # print struct with more effective memory layout or not, false by default + suggest-new: true + nakedret: + # make an issue if func has more lines of code than this setting and it has naked returns; default is 30 + max-func-lines: 30 + testpackage: + # regexp pattern to skip files + skip-regexp: (export|internal)_test\.go + unused: + # treat code as a program (not a library) and report unused exported identifiers; default is false. + # XXX: if you enable this setting, unused will report a lot of false-positives in text editors: + # if it's called for subdir of a project it can't find funcs usages. All text editor integrations + # with golangci-lint call it on a directory with the changed file. + check-exported: false + whitespace: + multi-if: false # Enforces newlines (or comments) after every multi-line if statement + multi-func: false # Enforces newlines (or comments) after every multi-line function signature + gci: + local-prefixes: "bitbucket.org" + misspell: + #locale: US + ignore-words: + wsl: + # If true append is only allowed to be cuddled if appending value is + # matching variables, fields or types on line above. Default is true. + strict-append: true + # Allow calls and assignments to be cuddled as long as the lines have any + # matching variables, fields or types. Default is true. + allow-assign-and-call: true + # Allow multiline assignments to be cuddled. Default is true. + allow-multiline-assign: true + # Allow declarations (var) to be cuddled. + allow-cuddle-declarations: false + # Allow trailing comments in ending of blocks + allow-trailing-comment: true + # Force newlines in end of case at this limit (0 = never). + force-case-trailing-whitespace: 0 + # Force cuddling of err checks with err var assignment + force-err-cuddling: false + # Allow leading comments to be separated with empty liens + allow-separated-leading-comment: false + custom: + # Each custom linter should have a unique name. + +linters: + enable: + - gofmt + - govet + - errcheck + - unused + - gosimple + - ineffassign + - typecheck + # Additional + # - lll + - godox + #- gomnd + - goconst + # - gocognit + # - nestif + # - gomodguard + - nakedret + - gci + - misspell + - gofumpt + - whitespace + - unconvert + - predeclared + - noctx + - dogsled + # - bodyclose + - asciicheck + #- stylecheck + # - unparam + # - wsl + + #disable-all: false + fast: true +issues: + # List of regexps of issue texts to exclude, empty list by default. + # But independently from this option we use default exclude patterns, + # it can be disabled by `exclude-use-default: false`. To list all + # excluded by default patterns execute `golangci-lint run --help` + exclude: + # Excluding configuration per-path, per-linter, per-text and per-source + exclude-rules: + # Exclude some linters from running on tests files. + # Independently from option `exclude` we use default exclude patterns, + # it can be disabled by this option. To list all + # excluded by default patterns execute `golangci-lint run --help`. + # Default value for this option is true. + exclude-use-default: false + # The default value is false. If set to true exclude and exclude-rules + # regular expressions become case sensitive. + exclude-case-sensitive: false + # The list of ids of default excludes to include or disable. By default it's empty. + include: + #- EXC0002 # disable excluding of issues about comments from golint + # Maximum issues count per one linter. Set to 0 to disable. Default is 50. + #max-issues-per-linter: 0 + # Maximum count of issues with the same text. Set to 0 to disable. Default is 3. + #max-same-issues: 0 + # Show only new issues: if there are unstaged changes or untracked files, + # only those changes are analyzed, else only changes in HEAD~ are analyzed. + # It's a super-useful option for integration of golangci-lint into existing + # large codebase. It's not practical to fix all existing issues at the moment + # of integration: much better don't allow issues in new code. + # Default is false. + new: false + # Show only new issues created after git revision `REV` + new-from-rev: "" + # Show only new issues created in git patch with set file path. + #new-from-patch: path/to/patch/file +severity: + # Default value is empty string. + # Set the default severity for issues. If severity rules are defined and the issues + # do not match or no severity is provided to the rule this will be the default + # severity applied. Severities should match the supported severity names of the + # selected out format. + # - Code climate: https://docs.codeclimate.com/docs/issues#issue-severity + # - Checkstyle: https://checkstyle.sourceforge.io/property_types.html#severity + # - Github: https://help.github.com/en/actions/reference/workflow-commands-for-github-actions#setting-an-error-message + default-severity: error + # The default value is false. + # If set to true severity-rules regular expressions become case sensitive. + case-sensitive: false + # Default value is empty list. + # When a list of severity rules are provided, severity information will be added to lint + # issues. Severity rules have the same filtering capability as exclude rules except you + # are allowed to specify one matcher per severity rule. + # Only affects out formats that support setting severity information. + rules: + - linters: + - gomnd + severity: ignore diff --git a/client.go b/client.go index c882d2a..d20e0dd 100644 --- a/client.go +++ b/client.go @@ -33,7 +33,6 @@ import ( "strconv" "strings" "time" - "unicode/utf8" "golang.org/x/net/http2" "golang.org/x/oauth2" @@ -83,7 +82,7 @@ func SelectHeaderAccept(accepts []string) string { // contains is a case insenstive match, finding needle in a haystack func contains(haystack []string, needle string) bool { for _, a := range haystack { - if strings.ToLower(a) == strings.ToLower(needle) { + if strings.EqualFold(a, needle) { return true } } @@ -99,7 +98,7 @@ func TypeCheckParameter(obj interface{}, expected string, name string) error { // Check the type is as expected. if reflect.TypeOf(obj).String() != expected { - return fmt.Errorf("Expected %s to be of type %s but received %s.", name, expected, reflect.TypeOf(obj).String()) + return fmt.Errorf("expected %s to be of type %s but received %s", name, expected, reflect.TypeOf(obj).String()) } return nil } @@ -162,7 +161,7 @@ func getContentID(v reflect.Value, ref string, class string) (contentID string, recursiveVal := v if ref[0] == '{' { contentID = ref[1 : len(ref)-1] - return + return contentID, err } if class != "" { var lastVal reflect.Value @@ -170,7 +169,7 @@ func getContentID(v reflect.Value, ref string, class string) (contentID string, lastVal = recursiveVal recursiveVal = recursiveVal.FieldByName(part) if !recursiveVal.IsValid() { - return "", fmt.Errorf("Do not have reference field %s in %s for multipart", part, lastVal.Type().String()) + return "", fmt.Errorf("do not have reference field %s in %s for multipart", part, lastVal.Type().String()) } if recursiveVal.Kind() == reflect.Ptr { if recursiveVal.IsNil() { @@ -216,14 +215,14 @@ func getContentID(v reflect.Value, ref string, class string) (contentID string, } } if i == lastValType.NumField() { - return "", fmt.Errorf("Do not have reference field Type %s in %s for multipart", fieldTypeString, lastValType.String()) + return "", fmt.Errorf("do not have reference field Type %s in %s for multipart", fieldTypeString, lastValType.String()) } } else { recursiveVal = recursiveVal.FieldByName(part) } if !recursiveVal.IsValid() { - return "", fmt.Errorf("Do not have reference field %s in %s for multipart", part, lastValType.String()) + return "", fmt.Errorf("do not have reference field %s in %s for multipart", part, lastValType.String()) } if recursiveVal.Kind() == reflect.Ptr { if recursiveVal.IsNil() { @@ -239,7 +238,7 @@ func getContentID(v reflect.Value, ref string, class string) (contentID string, } } contentID = recursiveVal.String() - return + return contentID, err } func MultipartEncode(v interface{}, body io.Writer) (string, error) { @@ -344,13 +343,12 @@ func PrepareRequest( formParams url.Values, formFileName string, fileName string, - fileBytes []byte) (localVarRequest *http.Request, err error) { - + fileBytes []byte, +) (localVarRequest *http.Request, err error) { var body *bytes.Buffer // Detect postBody type and post. if postBody != nil { - contentType := headerParams["Content-Type"] if contentType == "" { contentType = detectContentType(postBody) @@ -358,14 +356,12 @@ func PrepareRequest( } if strings.HasPrefix(headerParams["Content-Type"], "multipart/related") { - body = &bytes.Buffer{} contentType, err = MultipartEncode(postBody, body) if err != nil { return nil, err } headerParams["Content-Type"] = contentType - } else { body, err = setBody(postBody, contentType) if err != nil { @@ -377,7 +373,7 @@ func PrepareRequest( // add form parameters and file if available. if strings.HasPrefix(headerParams["Content-Type"], "multipart/form-data") && len(formParams) > 0 || (len(fileBytes) > 0 && fileName != "") { if body != nil { - return nil, errors.New("Cannot specify postBody and multipart form at the same time.") + return nil, errors.New("cannot specify postBody and multipart form at the same time") } body = &bytes.Buffer{} w := multipart.NewWriter(body) @@ -416,7 +412,7 @@ func PrepareRequest( if strings.HasPrefix(headerParams["Content-Type"], "application/x-www-form-urlencoded") && len(formParams) > 0 { if body != nil { - return nil, errors.New("Cannot specify postBody and x-www-form-urlencoded form at the same time.") + return nil, errors.New("cannot specify postBody and x-www-form-urlencoded form at the same time") } body = &bytes.Buffer{} body.WriteString(formParams.Encode()) @@ -507,6 +503,7 @@ func MultipartDeserialize(b []byte, v interface{}, boundary string) (err error) body := bytes.NewReader(b) r := multipart.NewReader(body, boundary) val := reflect.Indirect(reflect.ValueOf(v)) + var nextPart *multipart.Part contentIDIndex := make(map[string]int) @@ -515,7 +512,7 @@ func MultipartDeserialize(b []byte, v interface{}, boundary string) (err error) multipartBody := make([]byte, 1000) // if no remian part, break this loop - if nextPart, err := r.NextPart(); err == io.EOF { + if nextPart, err = r.NextPart(); err == io.EOF { break } else { part = nextPart @@ -525,7 +522,7 @@ func MultipartDeserialize(b []byte, v interface{}, boundary string) (err error) var n int n, err = part.Read(multipartBody) if err == nil { - return + return err } multipartBody = multipartBody[:n] @@ -628,9 +625,7 @@ func ReportError(format string, a ...interface{}) error { // set request body from an interface{} func setBody(body interface{}, contentType string) (bodyBuf *bytes.Buffer, err error) { - if bodyBuf == nil { - bodyBuf = &bytes.Buffer{} - } + bodyBuf = &bytes.Buffer{} if reader, ok := body.(io.Reader); ok { _, err = bodyBuf.ReadFrom(reader) @@ -653,7 +648,7 @@ func setBody(body interface{}, contentType string) (bodyBuf *bytes.Buffer, err e } if bodyBuf.Len() == 0 { - err = fmt.Errorf("Invalid body type %s\n", contentType) + err = fmt.Errorf("invalid body type %s", contentType) return nil, err } return bodyBuf, nil @@ -730,10 +725,6 @@ func CacheExpires(r *http.Response) time.Time { return expires } -func strlen(s string) int { - return utf8.RuneCountInString(s) -} - func InterceptH2CClient() { gock.InterceptClient(innerHTTP2CleartextClient) } diff --git a/convert_test.go b/convert_test.go index 77c1fb3..2a5d2d2 100644 --- a/convert_test.go +++ b/convert_test.go @@ -47,5 +47,8 @@ func TestConvert(t *testing.T) { 3: "three", }, to.M) expectTime, err := time.Parse(time.RFC3339, "2020-05-01T12:04:05+08:00") + if err != nil { + assert.FailNow(t, "failed to parse time") + } assert.Equal(t, expectTime, *to.DT) } diff --git a/json_query_builder.go b/json_query_builder.go index bf4ca03..a315a2d 100644 --- a/json_query_builder.go +++ b/json_query_builder.go @@ -7,6 +7,8 @@ package openapi import ( "encoding/json" "reflect" + + "github.com/omec-project/openapi/logger" ) func MarshToJsonString(v interface{}) (result []string) { @@ -14,11 +16,18 @@ func MarshToJsonString(v interface{}) (result []string) { val := reflect.ValueOf(v) if types.Kind() == reflect.Slice { for i := 0; i < val.Len(); i++ { - tmp, _ := json.Marshal(val.Index(i).Interface()) + tmp, err := json.Marshal(val.Index(i).Interface()) + if err != nil { + logger.OpenapiLog.Errorf("failed to json encode: %v", err) + } result = append(result, string(tmp)) } } else { - tmp, _ := json.Marshal(v) + tmp, err := json.Marshal(v) + if err != nil { + logger.OpenapiLog.Errorf("failed to json encode: %v", err) + } + result = append(result, string(tmp)) } return diff --git a/multipart_related.go b/multipart_related.go index 0621b9c..1e26dbf 100644 --- a/multipart_related.go +++ b/multipart_related.go @@ -10,6 +10,8 @@ import ( "io/ioutil" "net/http" "regexp" + + "github.com/omec-project/openapi/logger" ) type MultipartRelatedBinding struct{} @@ -27,7 +29,11 @@ func (MultipartRelatedBinding) Bind(req *http.Request, obj interface{}) error { } func (MultipartRelatedBinding) BindBody(body []byte, obj interface{}) error { - re, _ := regexp.Compile(`--([a-zA-Z0-9+\-_]+)--`) + re, err := regexp.Compile(`--([a-zA-Z0-9+\-_]+)--`) + if err != nil { + logger.OpenapiLog.Errorf("failed to parse expresion") + return errors.New("failed to parse expresion") + } submatch := re.FindSubmatch(body) if len(submatch) < 1 { return errors.New("cannot parse multipart boundary") diff --git a/nrfcache/match_filters.go b/nrfcache/match_filters.go index fad9752..4c62bc4 100644 --- a/nrfcache/match_filters.go +++ b/nrfcache/match_filters.go @@ -35,7 +35,6 @@ var matchFilters = MatchFilters{ } func MatchSmfProfile(profile *models.NfProfile, opts *Nnrf_NFDiscovery.SearchNFInstancesParamOpts) (bool, error) { - if opts.ServiceNames.IsSet() { reqServiceNames := opts.ServiceNames.Value().([]models.ServiceName) matchCount := 0 @@ -79,14 +78,12 @@ func MatchSmfProfile(profile *models.NfProfile, opts *Nnrf_NFDiscovery.SearchNFI } } } - } // if at least one matching snssai has been found if matchCount == 0 { return false, nil } - } // validate dnn @@ -109,7 +106,7 @@ func MatchSmfProfile(profile *models.NfProfile, opts *Nnrf_NFDiscovery.SearchNFI } } - if dnnMatched == false { + if !dnnMatched { return false, nil } } @@ -121,12 +118,15 @@ func MatchSupiRange(supi string, supiRange []models.SupiRange) bool { matchFound := false for _, s := range supiRange { if len(s.Pattern) > 0 { - r, _ := regexp.Compile(s.Pattern) + r, err := regexp.Compile(s.Pattern) + if err != nil { + logger.NrfcacheLog.Errorf("parsing pattern error: %v", err) + return false + } if r.MatchString(supi) { matchFound = true break } - } else if s.Start <= supi && supi <= s.End { matchFound = true break @@ -153,7 +153,6 @@ func MatchNssfProfile(profile *models.NfProfile, opts *Nnrf_NFDiscovery.SearchNF } func MatchAmfProfile(profile *models.NfProfile, opts *Nnrf_NFDiscovery.SearchNFInstancesParamOpts) (bool, error) { - if opts.TargetPlmnList.IsSet() { if profile.PlmnList != nil { plmnMatchCount := 0 @@ -162,7 +161,6 @@ func MatchAmfProfile(profile *models.NfProfile, opts *Nnrf_NFDiscovery.SearchNFI for _, targetPlmn := range targetPlmnList { var plmn models.PlmnId err := json.Unmarshal([]byte(targetPlmn), &plmn) - if err != nil { logger.NrfcacheLog.Errorf("error Unmarshaling plmn: %+v", err) return false, err @@ -190,7 +188,6 @@ func MatchAmfProfile(profile *models.NfProfile, opts *Nnrf_NFDiscovery.SearchNFI for _, guami := range guamiList { var guamiOpt models.Guami err := json.Unmarshal([]byte(guami), &guamiOpt) - if err != nil { logger.NrfcacheLog.Errorf("error Unmarshaling guami: %+v", err) return false, err diff --git a/nrfcache/nrfcache.go b/nrfcache/nrfcache.go index 73cce08..049ec3b 100644 --- a/nrfcache/nrfcache.go +++ b/nrfcache/nrfcache.go @@ -17,8 +17,10 @@ import ( "github.com/omec-project/openapi/models" ) -const defaultCacheTTl = time.Hour -const defaultNfProfileTTl = time.Minute +const ( + defaultCacheTTl = time.Hour + defaultNfProfileTTl = time.Minute +) type NfProfileItem struct { nfProfile *models.NfProfile @@ -296,7 +298,7 @@ func (c *NrfMasterCache) GetNrfCacheInstance(targetNfType models.NfType) *NrfCac defer c.mutex.Unlock() cache, exists := c.nfTypeToCacheMap[targetNfType] - if exists == false { + if !exists { logger.NrfcacheLog.Infof("creating cache for nftype %v", targetNfType) cache = NewNrfCache(c.evictionInterval, c.nrfDiscoveryQueryCb) c.nfTypeToCacheMap[targetNfType] = cache @@ -354,13 +356,11 @@ func SearchNFInstances(nrfUri string, targetNfType, requestNfType models.NfType, searchResult, err = c.handleLookup(nrfUri, targetNfType, requestNfType, param) } else { logger.NrfcacheLog.Errorln("failed to find cache for nf type") - } for _, np := range searchResult.NfInstances { logger.NrfcacheLog.Infof("%v", np) } return searchResult, err - } func RemoveNfProfileFromNrfCache(nfInstanceId string) bool { diff --git a/nrfcache/nrfcache_test.go b/nrfcache/nrfcache_test.go index 59c685d..49b71f1 100644 --- a/nrfcache/nrfcache_test.go +++ b/nrfcache/nrfcache_test.go @@ -17,18 +17,19 @@ import ( "time" "github.com/antihax/optional" - "github.com/omec-project/openapi/logger" "github.com/omec-project/openapi/Nnrf_NFDiscovery" + "github.com/omec-project/openapi/logger" "github.com/omec-project/openapi/models" ) -var nfProfilesDb map[string]string -var validityPeriod int32 -var evictionInterval int32 -var nrfDbCallbackCallCount int32 +var ( + nfProfilesDb map[string]string + validityPeriod int32 + evictionInterval int32 + nrfDbCallbackCallCount int32 +) func init() { - validityPeriod = 60 evictionInterval = 120 @@ -434,7 +435,6 @@ func init() { ] } } ` - } func MarshToJsonString(v interface{}) (result []string) { @@ -480,7 +480,6 @@ func getNfProfiles(targetNfType models.NfType) ([]models.NfProfile, error) { for key, elem := range nfProfilesDb { if strings.Contains(key, string(targetNfType)) { - var profile models.NfProfile err := json.Unmarshal([]byte(elem), &profile) if err != nil { @@ -495,7 +494,8 @@ func getNfProfiles(targetNfType models.NfType) ([]models.NfProfile, error) { } func nrfDbCallback(nrfUri string, targetNfType, requestNfType models.NfType, - param *Nnrf_NFDiscovery.SearchNFInstancesParamOpts) (models.SearchResult, error) { + param *Nnrf_NFDiscovery.SearchNFInstancesParamOpts, +) (models.SearchResult, error) { logger.NrfcacheLog.Infoln("nrfDbCallback Entry") nrfDbCallbackCallCount++ @@ -533,7 +533,6 @@ func nrfDbCallback(nrfUri string, targetNfType, requestNfType models.NfType, } searchResult.NfInstances = append(searchResult.NfInstances, nfProfile) - } else { searchResult.NfInstances, err = getNfProfiles(targetNfType) } @@ -547,7 +546,6 @@ func nrfDbCallback(nrfUri string, targetNfType, requestNfType models.NfType, } func TestCacheMissAndHits(t *testing.T) { - var result models.SearchResult var err error @@ -679,7 +677,6 @@ func TestCacheMissOnTTlExpiry(t *testing.T) { } result, err = SearchNFInstances("testNrf", models.NfType_SMF, models.NfType_AMF, ¶m) - if err != nil { t.Errorf("test failed, %s", err.Error()) } @@ -721,7 +718,6 @@ func TestCacheEviction(t *testing.T) { } result, err = SearchNFInstances("testNrf", models.NfType_SMF, models.NfType_AMF, ¶m) - if err != nil { t.Errorf("test failed, %s", err.Error()) } @@ -734,7 +730,6 @@ func TestCacheEviction(t *testing.T) { } result, err = SearchNFInstances("testNrf", models.NfType_SMF, models.NfType_AMF, ¶m) - if err != nil { t.Errorf("test failed, %s", err.Error()) } @@ -751,7 +746,6 @@ func TestCacheEviction(t *testing.T) { } func TestCacheConcurrency(t *testing.T) { - evictionTimerVal := time.Duration(evictionInterval) InitNrfCaching(evictionTimerVal*time.Second, nrfDbCallback) @@ -772,7 +766,6 @@ func TestCacheConcurrency(t *testing.T) { for i := 0; i < n; i++ { go func() { _, err := SearchNFInstances("testNrf", models.NfType_SMF, models.NfType_AMF, ¶m) - if err != nil { errCh <- err } @@ -792,7 +785,6 @@ func TestCacheConcurrency(t *testing.T) { t.Errorf("test timed out") case e := <-errCh: t.Errorf("error %s", e.Error()) - } if expectedCallCount != nrfDbCallbackCallCount { @@ -816,7 +808,6 @@ func TestAusfMatchFilters(t *testing.T) { expectedCallCount++ result, err := SearchNFInstances("testNrf", models.NfType_AUSF, models.NfType_AMF, ¶m) - if err != nil { t.Errorf("test failed, %s", err.Error()) } @@ -828,7 +819,6 @@ func TestAusfMatchFilters(t *testing.T) { } result, err = SearchNFInstances("testNrf", models.NfType_AUSF, models.NfType_AMF, ¶m) - if err != nil { t.Errorf("test failed, %s", err.Error()) } @@ -844,7 +834,6 @@ func TestAusfMatchFilters(t *testing.T) { } result, err = SearchNFInstances("testNrf", models.NfType_AUSF, models.NfType_AMF, ¶m) - if err != nil { t.Errorf("test failed, %s", err.Error()) } @@ -870,7 +859,6 @@ func TestAmfMatchFilters(t *testing.T) { expectedCallCount++ result, err := SearchNFInstances("testNrf", models.NfType_AMF, models.NfType_AMF, ¶m) - if err != nil { t.Errorf("test failed, %s", err.Error()) } @@ -888,7 +876,6 @@ func TestAmfMatchFilters(t *testing.T) { } result, err = SearchNFInstances("testNrf", models.NfType_AMF, models.NfType_AMF, ¶m) - if err != nil { t.Errorf("test failed, %s", err.Error()) } diff --git a/supported_feature_test.go b/supported_feature_test.go index f83439c..e64d844 100644 --- a/supported_feature_test.go +++ b/supported_feature_test.go @@ -28,8 +28,12 @@ func TestNewSupportedFeature(t *testing.T) { assert.NotNil(t, err, "should retrun error") assert.Equal(t, SupportedFeature{}, suppFeat) } + func TestGetFeatureOfSupportedFeature(t *testing.T) { - suppFeat, _ := NewSupportedFeature("1324") + suppFeat, err := NewSupportedFeature("1324") + if err != nil { + assert.FailNow(t, "failed to create new supported feature from string") + } assert.False(t, suppFeat.GetFeature(1)) assert.False(t, suppFeat.GetFeature(2)) @@ -53,41 +57,81 @@ func TestGetFeatureOfSupportedFeature(t *testing.T) { } func TestStringOfSupportedFeature(t *testing.T) { - suppFeat, _ := NewSupportedFeature("1324") + suppFeat, err := NewSupportedFeature("1324") + if err != nil { + assert.FailNow(t, "failed to create new supported feature from string") + } assert.Equal(t, "1324", suppFeat.String()) // testing padding - suppFeat, _ = NewSupportedFeature("1") + suppFeat, err = NewSupportedFeature("1") + if err != nil { + assert.FailNow(t, "failed to create new supported feature from string") + } assert.Equal(t, "01", suppFeat.String()) - suppFeat, _ = NewSupportedFeature("ABCDE") + suppFeat, err = NewSupportedFeature("ABCDE") + if err != nil { + assert.FailNow(t, "failed to create new supported feature from string") + } assert.Equal(t, "0abcde", suppFeat.String()) } func TestNegotiateWithOfSupportedFeature(t *testing.T) { var suppFeatA, suppFeatB, negotiatedFeat SupportedFeature - suppFeatA, _ = NewSupportedFeature("0FFF") - suppFeatB, _ = NewSupportedFeature("1324") + var err error + suppFeatA, err = NewSupportedFeature("0FFF") + if err != nil { + assert.FailNow(t, "failed to create new supported feature from string") + } + suppFeatB, err = NewSupportedFeature("1324") + if err != nil { + assert.FailNow(t, "failed to create new supported feature from string") + } negotiatedFeat = suppFeatA.NegotiateWith(suppFeatB) assert.Equal(t, SupportedFeature{0x03, 0x24}, negotiatedFeat) - suppFeatA, _ = NewSupportedFeature("0234") - suppFeatB, _ = NewSupportedFeature("0001") + suppFeatA, err = NewSupportedFeature("0234") + if err != nil { + assert.FailNow(t, "failed to create new supported feature from string") + } + suppFeatB, err = NewSupportedFeature("0001") + if err != nil { + assert.FailNow(t, "failed to create new supported feature from string") + } negotiatedFeat = suppFeatA.NegotiateWith(suppFeatB) assert.Equal(t, SupportedFeature{0x00, 0x00}, negotiatedFeat) - suppFeatA, _ = NewSupportedFeature("FFFF") - suppFeatB, _ = NewSupportedFeature("F") + suppFeatA, err = NewSupportedFeature("FFFF") + if err != nil { + assert.FailNow(t, "failed to create new supported feature from string") + } + suppFeatB, err = NewSupportedFeature("F") + if err != nil { + assert.FailNow(t, "failed to create new supported feature from string") + } negotiatedFeat = suppFeatA.NegotiateWith(suppFeatB) assert.Equal(t, SupportedFeature{0x00, 0x0F}, negotiatedFeat) - suppFeatA, _ = NewSupportedFeature("3000") - suppFeatB, _ = NewSupportedFeature("3") + suppFeatA, err = NewSupportedFeature("3000") + if err != nil { + assert.FailNow(t, "failed to create new supported feature from string") + } + suppFeatB, err = NewSupportedFeature("3") + if err != nil { + assert.FailNow(t, "failed to create new supported feature from string") + } negotiatedFeat = suppFeatA.NegotiateWith(suppFeatB) assert.Equal(t, SupportedFeature{0x00, 0x00}, negotiatedFeat) - suppFeatA, _ = NewSupportedFeature("23E3") - suppFeatB, _ = NewSupportedFeature("1") + suppFeatA, err = NewSupportedFeature("23E3") + if err != nil { + assert.FailNow(t, "failed to create new supported feature from string") + } + suppFeatB, err = NewSupportedFeature("1") + if err != nil { + assert.FailNow(t, "failed to create new supported feature from string") + } negotiatedFeat = suppFeatA.NegotiateWith(suppFeatB) assert.Equal(t, SupportedFeature{0x00, 0x01}, negotiatedFeat) }