snapshot of https://github.com/mattermost/mattermost.git (master, 2026-09-16; blobs > 131072B omitted)
Some checks failed
Server CI / Postgres (shard 0) (push) Has been skipped
Server CI / Postgres (shard 3) (push) Has been skipped
BuildEnv Docker Image / build-image (push) Failing after 4s
BuildEnv Docker Image / build-image-fips (push) Failing after 4s
Migration Review & Release Notes / Generate migration review & release notes (push) Failing after 3s
Server CI / Build Environment (push) Failing after 3s
Server CI / Postgres (shard 1) (push) Has been skipped
Tools CI / check-style (mattermost-govet) (push) Failing after 4s
Server CI / Postgres (shard 2) (push) Has been skipped
Tools CI / check-style (mmgotool) (push) Failing after 3s
Server CI / Elasticsearch v8 Compatibility (push) Has been skipped
Server CI / OpenSearch v2 Compatibility (push) Has been skipped
Server CI / Postgres FIPS (shard 0) (push) Has been skipped
Tools CI / Test (mattermost-govet) (push) Failing after 3s
Server CI / Postgres FIPS (shard 1) (push) Has been skipped
Server CI / Postgres FIPS (shard 2) (push) Has been skipped
Tools CI / Test (mmgotool) (push) Failing after 3s
Server CI / Postgres FIPS (shard 3) (push) Has been skipped
Server CI / Run mmctl tests (push) Has been skipped
Server CI / Run mmctl tests (FIPS) (push) Has been skipped
Server CI / Merge Postgres Test Results (push) Has been skipped
Server CI / Merge Postgres FIPS Test Results (push) Has been skipped
Server CI / Check backport migrations (push) Has been skipped
Server CI / Check generated files (push) Has been skipped
Server CI / check-style (push) Has been skipped
Server CI / Vet API (push) Has been skipped
Server CI / Build mattermost server app (push) Has been skipped
Server CI / Server CI Complete (push) Failing after 2s
Server CI / Server CI Artifacts (push) Has been skipped
Server CI / Sentry Upload (push) Has been skipped
Server CI / Server CI Report (push) Failing after 5m1s
Server CI Nightly Race / Race Detector (push) Has been skipped
CodeQL / Analyze (go) (push) Has been cancelled
CodeQL / Analyze (javascript) (push) Has been cancelled
Webapp CI Cache Warm / Warm Webapp node_modules Cache (push) Has been cancelled
E2E CI Cache Warm / Warm E2E npm Registry Cache (push) Has been cancelled
API / build (push) Has been cancelled
Web App CI / check-types (push) Has been cancelled
Web App CI / check-lint (push) Has been cancelled
Web App CI / check-i18n (push) Has been cancelled
Web App CI / check-external-links (push) Has been cancelled
Web App CI / test (platform) (push) Has been cancelled
Web App CI / test (mattermost-redux) (push) Has been cancelled
Web App CI / test (channels shard 1/4) (push) Has been cancelled
Web App CI / test (channels shard 2/4) (push) Has been cancelled
Web App CI / test (channels shard 3/4) (push) Has been cancelled
Web App CI / test (channels shard 4/4) (push) Has been cancelled
Web App CI / upload-coverage (push) Has been cancelled
Web App CI / build (push) Has been cancelled
YAML Lint / yamllint (push) Has been cancelled
Push mirrored docker images / cd/Push mirrored docker images (push) Has been cancelled
docs-cd / Build and deploy docs (push) Has been cancelled
Docs CI / build (push) Has been cancelled
E2E Cache Warm: Cypress deps / Warm Cypress deps cache (push) Has been cancelled
Scorecards supply-chain security / Scorecard analysis (push) Has been cancelled
Server CI Weekly / Postgres FIPS (push) Has been skipped
Server CI Weekly / Run mmctl tests (FIPS) (push) Has been skipped
Server CI Weekly / Postgres with binary parameters (push) Has been skipped
Server CI Weekly / Build Environment (push) Failing after 1s
Server CI Cache Warm / Warm Go Module and Build Cache (push) Failing after 2s
Server CI Nightly Race / Build Environment (push) Failing after 1s
Some checks failed
Server CI / Postgres (shard 0) (push) Has been skipped
Server CI / Postgres (shard 3) (push) Has been skipped
BuildEnv Docker Image / build-image (push) Failing after 4s
BuildEnv Docker Image / build-image-fips (push) Failing after 4s
Migration Review & Release Notes / Generate migration review & release notes (push) Failing after 3s
Server CI / Build Environment (push) Failing after 3s
Server CI / Postgres (shard 1) (push) Has been skipped
Tools CI / check-style (mattermost-govet) (push) Failing after 4s
Server CI / Postgres (shard 2) (push) Has been skipped
Tools CI / check-style (mmgotool) (push) Failing after 3s
Server CI / Elasticsearch v8 Compatibility (push) Has been skipped
Server CI / OpenSearch v2 Compatibility (push) Has been skipped
Server CI / Postgres FIPS (shard 0) (push) Has been skipped
Tools CI / Test (mattermost-govet) (push) Failing after 3s
Server CI / Postgres FIPS (shard 1) (push) Has been skipped
Server CI / Postgres FIPS (shard 2) (push) Has been skipped
Tools CI / Test (mmgotool) (push) Failing after 3s
Server CI / Postgres FIPS (shard 3) (push) Has been skipped
Server CI / Run mmctl tests (push) Has been skipped
Server CI / Run mmctl tests (FIPS) (push) Has been skipped
Server CI / Merge Postgres Test Results (push) Has been skipped
Server CI / Merge Postgres FIPS Test Results (push) Has been skipped
Server CI / Check backport migrations (push) Has been skipped
Server CI / Check generated files (push) Has been skipped
Server CI / check-style (push) Has been skipped
Server CI / Vet API (push) Has been skipped
Server CI / Build mattermost server app (push) Has been skipped
Server CI / Server CI Complete (push) Failing after 2s
Server CI / Server CI Artifacts (push) Has been skipped
Server CI / Sentry Upload (push) Has been skipped
Server CI / Server CI Report (push) Failing after 5m1s
Server CI Nightly Race / Race Detector (push) Has been skipped
CodeQL / Analyze (go) (push) Has been cancelled
CodeQL / Analyze (javascript) (push) Has been cancelled
Webapp CI Cache Warm / Warm Webapp node_modules Cache (push) Has been cancelled
E2E CI Cache Warm / Warm E2E npm Registry Cache (push) Has been cancelled
API / build (push) Has been cancelled
Web App CI / check-types (push) Has been cancelled
Web App CI / check-lint (push) Has been cancelled
Web App CI / check-i18n (push) Has been cancelled
Web App CI / check-external-links (push) Has been cancelled
Web App CI / test (platform) (push) Has been cancelled
Web App CI / test (mattermost-redux) (push) Has been cancelled
Web App CI / test (channels shard 1/4) (push) Has been cancelled
Web App CI / test (channels shard 2/4) (push) Has been cancelled
Web App CI / test (channels shard 3/4) (push) Has been cancelled
Web App CI / test (channels shard 4/4) (push) Has been cancelled
Web App CI / upload-coverage (push) Has been cancelled
Web App CI / build (push) Has been cancelled
YAML Lint / yamllint (push) Has been cancelled
Push mirrored docker images / cd/Push mirrored docker images (push) Has been cancelled
docs-cd / Build and deploy docs (push) Has been cancelled
Docs CI / build (push) Has been cancelled
E2E Cache Warm: Cypress deps / Warm Cypress deps cache (push) Has been cancelled
Scorecards supply-chain security / Scorecard analysis (push) Has been cancelled
Server CI Weekly / Postgres FIPS (push) Has been skipped
Server CI Weekly / Run mmctl tests (FIPS) (push) Has been skipped
Server CI Weekly / Postgres with binary parameters (push) Has been skipped
Server CI Weekly / Build Environment (push) Failing after 1s
Server CI Cache Warm / Warm Go Module and Build Cache (push) Failing after 2s
Server CI Nightly Race / Build Environment (push) Failing after 1s
This commit is contained in:
352
server/public/utils/json_test.go
Normal file
352
server/public/utils/json_test.go
Normal file
@@ -0,0 +1,352 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
package utils_test
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
"github.com/mattermost/mattermost/server/public/utils"
|
||||
)
|
||||
|
||||
func TestHumanizeJsonError(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
type testType struct{}
|
||||
|
||||
testCases := []struct {
|
||||
Description string
|
||||
Data []byte
|
||||
Err error
|
||||
ExpectedErr string
|
||||
}{
|
||||
{
|
||||
"nil error",
|
||||
[]byte{},
|
||||
nil,
|
||||
"",
|
||||
},
|
||||
{
|
||||
"non-special error",
|
||||
[]byte{},
|
||||
errors.New("test"),
|
||||
"test",
|
||||
},
|
||||
{
|
||||
"syntax error, offset 17, middle of line 3",
|
||||
[]byte("line 1\nline 2\nline 3"),
|
||||
&json.SyntaxError{
|
||||
// msg can't be set
|
||||
Offset: 17,
|
||||
},
|
||||
"parsing error at line 3, character 4: ",
|
||||
},
|
||||
{
|
||||
"unmarshal type error, offset 17, middle of line 3",
|
||||
[]byte("line 1\nline 2\nline 3"),
|
||||
&json.UnmarshalTypeError{
|
||||
Value: "bool",
|
||||
Type: reflect.TypeFor[testType](),
|
||||
Offset: 17,
|
||||
Struct: "struct",
|
||||
Field: "field",
|
||||
},
|
||||
"parsing error at line 3, character 4: json: cannot unmarshal bool into Go struct field struct.field of type utils_test.testType",
|
||||
},
|
||||
}
|
||||
|
||||
for _, testCase := range testCases {
|
||||
t.Run(testCase.Description, func(t *testing.T) {
|
||||
actual := utils.HumanizeJSONError(testCase.Err, testCase.Data)
|
||||
if testCase.ExpectedErr == "" {
|
||||
assert.NoError(t, actual)
|
||||
} else {
|
||||
assert.EqualError(t, actual, testCase.ExpectedErr)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestNewHumanizedJSONError(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
testCases := []struct {
|
||||
Description string
|
||||
Data []byte
|
||||
Offset int64
|
||||
Err error
|
||||
Expected *utils.HumanizedJSONError
|
||||
}{
|
||||
{
|
||||
"nil error",
|
||||
[]byte{},
|
||||
0,
|
||||
nil,
|
||||
nil,
|
||||
},
|
||||
{
|
||||
"offset -1, before start of string",
|
||||
[]byte("line 1\nline 2\nline 3"),
|
||||
-1,
|
||||
errors.New("message"),
|
||||
&utils.HumanizedJSONError{
|
||||
Err: errors.Wrap(errors.New("message"), "invalid offset -1"),
|
||||
},
|
||||
},
|
||||
{
|
||||
"offset 0, start of string",
|
||||
[]byte("line 1\nline 2\nline 3"),
|
||||
0,
|
||||
errors.New("message"),
|
||||
&utils.HumanizedJSONError{
|
||||
Err: errors.Wrap(errors.New("message"), "parsing error at line 1, character 1"),
|
||||
Line: 1,
|
||||
Character: 1,
|
||||
},
|
||||
},
|
||||
{
|
||||
"offset 5, end of line 1",
|
||||
[]byte("line 1\nline 2\nline 3"),
|
||||
5,
|
||||
errors.New("message"),
|
||||
&utils.HumanizedJSONError{
|
||||
Err: errors.Wrap(errors.New("message"), "parsing error at line 1, character 6"),
|
||||
Line: 1,
|
||||
Character: 6,
|
||||
},
|
||||
},
|
||||
{
|
||||
"offset 6, new line at end end of line 1",
|
||||
[]byte("line 1\nline 2\nline 3"),
|
||||
6,
|
||||
errors.New("message"),
|
||||
&utils.HumanizedJSONError{
|
||||
Err: errors.Wrap(errors.New("message"), "parsing error at line 1, character 7"),
|
||||
Line: 1,
|
||||
Character: 7,
|
||||
},
|
||||
},
|
||||
{
|
||||
"offset 7, start of line 2",
|
||||
[]byte("line 1\nline 2\nline 3"),
|
||||
7,
|
||||
errors.New("message"),
|
||||
&utils.HumanizedJSONError{
|
||||
Err: errors.Wrap(errors.New("message"), "parsing error at line 2, character 1"),
|
||||
Line: 2,
|
||||
Character: 1,
|
||||
},
|
||||
},
|
||||
{
|
||||
"offset 12, end of line 2",
|
||||
[]byte("line 1\nline 2\nline 3"),
|
||||
12,
|
||||
errors.New("message"),
|
||||
&utils.HumanizedJSONError{
|
||||
Err: errors.Wrap(errors.New("message"), "parsing error at line 2, character 6"),
|
||||
Line: 2,
|
||||
Character: 6,
|
||||
},
|
||||
},
|
||||
{
|
||||
"offset 13, newline at end of line 2",
|
||||
[]byte("line 1\nline 2\nline 3"),
|
||||
13,
|
||||
errors.New("message"),
|
||||
&utils.HumanizedJSONError{
|
||||
Err: errors.Wrap(errors.New("message"), "parsing error at line 2, character 7"),
|
||||
Line: 2,
|
||||
Character: 7,
|
||||
},
|
||||
},
|
||||
{
|
||||
"offset 17, middle of line 3",
|
||||
[]byte("line 1\nline 2\nline 3"),
|
||||
17,
|
||||
errors.New("message"),
|
||||
&utils.HumanizedJSONError{
|
||||
Err: errors.Wrap(errors.New("message"), "parsing error at line 3, character 4"),
|
||||
Line: 3,
|
||||
Character: 4,
|
||||
},
|
||||
},
|
||||
{
|
||||
"offset 19, end of string",
|
||||
[]byte("line 1\nline 2\nline 3"),
|
||||
19,
|
||||
errors.New("message"),
|
||||
&utils.HumanizedJSONError{
|
||||
Err: errors.Wrap(errors.New("message"), "parsing error at line 3, character 6"),
|
||||
Line: 3,
|
||||
Character: 6,
|
||||
},
|
||||
},
|
||||
{
|
||||
"offset 20, offset = length of string",
|
||||
[]byte("line 1\nline 2\nline 3"),
|
||||
20,
|
||||
errors.New("message"),
|
||||
&utils.HumanizedJSONError{
|
||||
Err: errors.Wrap(errors.New("message"), "parsing error at line 3, character 7"),
|
||||
Line: 3,
|
||||
Character: 7,
|
||||
},
|
||||
},
|
||||
{
|
||||
"offset 21, offset = length of string, after newline",
|
||||
[]byte("line 1\nline 2\nline 3\n"),
|
||||
21,
|
||||
errors.New("message"),
|
||||
&utils.HumanizedJSONError{
|
||||
Err: errors.Wrap(errors.New("message"), "parsing error at line 4, character 1"),
|
||||
Line: 4,
|
||||
Character: 1,
|
||||
},
|
||||
},
|
||||
{
|
||||
"offset 21, offset > length of string",
|
||||
[]byte("line 1\nline 2\nline 3"),
|
||||
21,
|
||||
errors.New("message"),
|
||||
&utils.HumanizedJSONError{
|
||||
Err: errors.Wrap(errors.New("message"), "invalid offset 21"),
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, testCase := range testCases {
|
||||
t.Run(testCase.Description, func(t *testing.T) {
|
||||
actual := utils.NewHumanizedJSONError(testCase.Err, testCase.Data, testCase.Offset)
|
||||
if testCase.Expected != nil && actual.Err != nil {
|
||||
if assert.EqualValues(t, testCase.Expected.Err.Error(), actual.Err.Error()) {
|
||||
actual.Err = testCase.Expected.Err
|
||||
}
|
||||
}
|
||||
assert.Equal(t, testCase.Expected, actual)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestIsJSONEmpty(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
testCases := []struct {
|
||||
Description string
|
||||
Data []byte
|
||||
Empty bool
|
||||
}{
|
||||
{
|
||||
"nil []byte is empty",
|
||||
nil,
|
||||
true,
|
||||
},
|
||||
{
|
||||
"Zero length slice is empty",
|
||||
[]byte(""),
|
||||
true,
|
||||
},
|
||||
{
|
||||
"braces are empty",
|
||||
[]byte("{}"),
|
||||
true,
|
||||
},
|
||||
{
|
||||
"square brackets are empty",
|
||||
[]byte("[]"),
|
||||
true,
|
||||
},
|
||||
{
|
||||
"empty string is empty",
|
||||
[]byte("\"\""),
|
||||
true,
|
||||
},
|
||||
{
|
||||
"map is not empty",
|
||||
[]byte("{\"foo\":7}"),
|
||||
false,
|
||||
},
|
||||
{
|
||||
"array is not empty",
|
||||
[]byte("[1,2,3]"),
|
||||
false,
|
||||
},
|
||||
{
|
||||
"string is not empty",
|
||||
[]byte("\"hello\""),
|
||||
false,
|
||||
},
|
||||
{
|
||||
"whitespace still empty",
|
||||
[]byte(" \n { \t } "),
|
||||
true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, testCase := range testCases {
|
||||
t.Run(testCase.Description, func(t *testing.T) {
|
||||
empty := utils.IsEmptyJSON(testCase.Data)
|
||||
assert.Equal(t, testCase.Empty, empty)
|
||||
|
||||
if !testCase.Empty {
|
||||
// don't really need to test the JSON unmarshaller but this is included
|
||||
// to ensure the test cases stay valid.
|
||||
var v any
|
||||
err := json.Unmarshal(testCase.Data, &v)
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestStringPtrToJSON(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
testCases := []struct {
|
||||
Description string
|
||||
Ptr *string
|
||||
Expect json.RawMessage
|
||||
}{
|
||||
{
|
||||
"nil string ptr",
|
||||
nil,
|
||||
[]byte("{}"),
|
||||
},
|
||||
{
|
||||
"Zero length string",
|
||||
new(""),
|
||||
[]byte("{}"),
|
||||
},
|
||||
{
|
||||
"JSON map",
|
||||
new("{\"foo\":7}"),
|
||||
[]byte("{\"foo\":7}"),
|
||||
},
|
||||
{
|
||||
"JSON array",
|
||||
new("[1,2,3]"),
|
||||
[]byte("[1,2,3]"),
|
||||
},
|
||||
{
|
||||
"JSON string",
|
||||
new("\"hello\""),
|
||||
[]byte("\"hello\""),
|
||||
},
|
||||
{
|
||||
"bare string",
|
||||
new("hello"),
|
||||
[]byte("\"hello\""),
|
||||
},
|
||||
}
|
||||
|
||||
for _, testCase := range testCases {
|
||||
t.Run(testCase.Description, func(t *testing.T) {
|
||||
j := utils.StringPtrToJSON(testCase.Ptr)
|
||||
assert.Equal(t, testCase.Expect, j)
|
||||
})
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user