mirror of
https://github.com/hanzoai/team.git
synced 2026-09-30 01:57:35 +00:00
The server module named github.com/hanzoai/team/server/v8 — a path that resolves to the retired workspace's repository, not this one — while server/public still published github.com/mattermost/mattermost/server/public. Both are github.com/hanzoteam/server/... now, which is where this code actually lives. That second half is what made the binary unbootable. Upstream's public path stayed claimed by upstream, mattermost-plugin-ai imported it, and the build linked public/model twice; public/plugin's gob.Register then ran twice under one name and panicked at init, before main. Reverting the rename traded the brand for a working binary. Rebranding the plugin alongside it needs no such trade: the agents fork is github.com/hanzoteam/agents/v2 against our public module, so no module named mattermost/mattermost is in the graph at all. Measured: `go list -deps ./cmd/mattermost` names exactly one public/model, and it is ours.
256 lines
6.2 KiB
Go
256 lines
6.2 KiB
Go
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
|
// See LICENSE.txt for license information.
|
|
|
|
package imaging
|
|
|
|
import (
|
|
"bytes"
|
|
"image"
|
|
"image/color"
|
|
"os"
|
|
"path/filepath"
|
|
"testing"
|
|
|
|
"github.com/hanzoteam/server/server/v8/channels/utils/fileutils"
|
|
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
// requireSameImage asserts that want and got cover the same bounds and have
|
|
// identical RGBA values at every pixel. We compare decoded pixels rather than
|
|
// re-encoded byte streams because image/png is not byte-stable across Go
|
|
// versions even for identical pixel content. On mismatch we walk every pixel
|
|
// before failing so the report includes the total diff rate, not just the
|
|
// first divergence.
|
|
func requireSameImage(t *testing.T, want, got image.Image) {
|
|
t.Helper()
|
|
require.Equal(t, want.Bounds(), got.Bounds())
|
|
b := got.Bounds()
|
|
total := b.Dx() * b.Dy()
|
|
var (
|
|
diff int
|
|
firstX int
|
|
firstY int
|
|
firstWant [4]uint32
|
|
firstGot [4]uint32
|
|
)
|
|
for y := b.Min.Y; y < b.Max.Y; y++ {
|
|
for x := b.Min.X; x < b.Max.X; x++ {
|
|
wr, wg, wb, wa := want.At(x, y).RGBA()
|
|
gr, gg, gb, ga := got.At(x, y).RGBA()
|
|
if wr == gr && wg == gg && wb == gb && wa == ga {
|
|
continue
|
|
}
|
|
if diff == 0 {
|
|
firstX, firstY = x, y
|
|
firstWant = [4]uint32{wr, wg, wb, wa}
|
|
firstGot = [4]uint32{gr, gg, gb, ga}
|
|
}
|
|
diff++
|
|
}
|
|
}
|
|
if diff > 0 {
|
|
t.Fatalf("%d / %d pixels differ (%.2f%%); first at (%d, %d): want %v got %v",
|
|
diff, total, 100*float64(diff)/float64(total),
|
|
firstX, firstY, firstWant, firstGot)
|
|
}
|
|
}
|
|
|
|
func TestFillImageTransparency(t *testing.T) {
|
|
tcs := []struct {
|
|
name string
|
|
inputName string
|
|
outputName string
|
|
fillColor color.Color
|
|
}{
|
|
{
|
|
"8-bit Palette",
|
|
"fill_test_8bit_palette.png",
|
|
"fill_test_8bit_palette_out.png",
|
|
color.RGBA{0, 255, 0, 255},
|
|
},
|
|
{
|
|
"8-bit RGB",
|
|
"fill_test_8bit_rgb.png",
|
|
"fill_test_8bit_rgb_out.png",
|
|
color.RGBA{0, 255, 0, 255},
|
|
},
|
|
{
|
|
"8-bit RGBA",
|
|
"fill_test_8bit_rgba.png",
|
|
"fill_test_8bit_rgba_out.png",
|
|
color.RGBA{0, 255, 0, 255},
|
|
},
|
|
{
|
|
"16-bit RGB",
|
|
"fill_test_16bit_rgb.png",
|
|
"fill_test_16bit_rgb_out.png",
|
|
color.RGBA{0, 255, 0, 255},
|
|
},
|
|
{
|
|
"16-bit RGBA",
|
|
"fill_test_16bit_rgba.png",
|
|
"fill_test_16bit_rgba_out.png",
|
|
color.RGBA{0, 255, 0, 255},
|
|
},
|
|
}
|
|
|
|
imgDir, ok := fileutils.FindDir("tests")
|
|
require.True(t, ok)
|
|
|
|
e, err := NewEncoder(EncoderOptions{})
|
|
require.NotNil(t, e)
|
|
require.NoError(t, err)
|
|
|
|
d, err := NewDecoder(DecoderOptions{})
|
|
require.NotNil(t, d)
|
|
require.NoError(t, err)
|
|
|
|
for _, tc := range tcs {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
inputFile, err := os.Open(imgDir + "/" + tc.inputName)
|
|
require.NoError(t, err)
|
|
require.NotNil(t, inputFile)
|
|
defer func() {
|
|
require.NoError(t, inputFile.Close())
|
|
}()
|
|
|
|
inputImg, format, err := d.Decode(inputFile)
|
|
require.NoError(t, err)
|
|
require.NotNil(t, inputImg)
|
|
require.Equal(t, "png", format)
|
|
|
|
expectedBytes, err := os.ReadFile(imgDir + "/" + tc.outputName)
|
|
require.NoError(t, err)
|
|
|
|
FillImageTransparency(inputImg, tc.fillColor)
|
|
|
|
var b bytes.Buffer
|
|
err = e.EncodePNG(&b, inputImg)
|
|
require.NoError(t, err)
|
|
require.Equal(t, expectedBytes, b.Bytes())
|
|
})
|
|
}
|
|
|
|
t.Run("Opaque image", func(t *testing.T) {
|
|
inputFile, err := os.Open(imgDir + "/fill_test_opaque.png")
|
|
require.NoError(t, err)
|
|
require.NotNil(t, inputFile)
|
|
defer func() {
|
|
require.NoError(t, inputFile.Close())
|
|
}()
|
|
|
|
inputImg, format, err := d.Decode(inputFile)
|
|
require.NoError(t, err)
|
|
require.NotNil(t, inputImg)
|
|
require.Equal(t, "png", format)
|
|
|
|
_, err = inputFile.Seek(0, 0)
|
|
require.NoError(t, err)
|
|
|
|
expectedImg, format, err := d.Decode(inputFile)
|
|
require.NoError(t, err)
|
|
require.NotNil(t, expectedImg)
|
|
require.Equal(t, "png", format)
|
|
|
|
FillImageTransparency(inputImg, color.RGBA{0, 255, 0, 255})
|
|
require.Equal(t, expectedImg, inputImg)
|
|
})
|
|
}
|
|
|
|
func TestFillCenter(t *testing.T) {
|
|
tcs := []struct {
|
|
name string
|
|
outputName string
|
|
width int
|
|
height int
|
|
}{
|
|
{"100x100", "fill_test_output_100x100.png", 100, 100},
|
|
{"45x45", "fill_test_output_45x45.png", 45, 45},
|
|
{"100x45", "fill_test_output_100x45.png", 100, 45},
|
|
{"45x100", "fill_test_output_45x100.png", 45, 100},
|
|
}
|
|
|
|
imgDir, ok := fileutils.FindDir("tests")
|
|
require.True(t, ok)
|
|
|
|
d, err := NewDecoder(DecoderOptions{})
|
|
require.NoError(t, err)
|
|
require.NotNil(t, d)
|
|
|
|
inputFile, err := os.Open(filepath.Join(imgDir, "fill_test_input.png"))
|
|
require.NoError(t, err)
|
|
defer inputFile.Close()
|
|
|
|
inputImg, format, err := d.Decode(inputFile)
|
|
require.NoError(t, err)
|
|
require.Equal(t, "png", format)
|
|
|
|
for _, tc := range tcs {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
expectedFile, err := os.Open(filepath.Join(imgDir, tc.outputName))
|
|
require.NoError(t, err)
|
|
defer expectedFile.Close()
|
|
|
|
expectedImg, format, err := d.Decode(expectedFile)
|
|
require.NoError(t, err)
|
|
require.Equal(t, "png", format)
|
|
|
|
out := FillCenter(inputImg, tc.width, tc.height)
|
|
requireSameImage(t, expectedImg, out)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestFit(t *testing.T) {
|
|
tcs := []struct {
|
|
name string
|
|
inputImg image.Image
|
|
maxW int
|
|
maxH int
|
|
expectedWidth int
|
|
expectedHeight int
|
|
}{
|
|
{
|
|
name: "no resize when smaller than bounds",
|
|
inputImg: image.NewRGBA(image.Rect(0, 0, 50, 50)),
|
|
maxW: 100,
|
|
maxH: 100,
|
|
expectedWidth: 50,
|
|
expectedHeight: 50,
|
|
},
|
|
{
|
|
name: "landscape clamps to width",
|
|
inputImg: image.NewRGBA(image.Rect(0, 0, 200, 100)),
|
|
maxW: 100,
|
|
maxH: 100,
|
|
expectedWidth: 100,
|
|
expectedHeight: 50,
|
|
},
|
|
{
|
|
name: "portrait clamps to height",
|
|
inputImg: image.NewRGBA(image.Rect(0, 0, 100, 200)),
|
|
maxW: 100,
|
|
maxH: 100,
|
|
expectedWidth: 50,
|
|
expectedHeight: 100,
|
|
},
|
|
{
|
|
name: "both dimensions exceed",
|
|
inputImg: image.NewRGBA(image.Rect(0, 0, 400, 200)),
|
|
maxW: 100,
|
|
maxH: 100,
|
|
expectedWidth: 100,
|
|
expectedHeight: 50,
|
|
},
|
|
}
|
|
|
|
for _, tc := range tcs {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
out := Fit(tc.inputImg, tc.maxW, tc.maxH)
|
|
require.Equal(t, tc.expectedWidth, out.Bounds().Dx())
|
|
require.Equal(t, tc.expectedHeight, out.Bounds().Dy())
|
|
})
|
|
}
|
|
}
|