mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2024-12-24 02:38:53 +01:00
internal/buffered: move tests to internal/beforemaintest
Also, this change moves TestUnsyncedPixels to buffered_test.
This commit is contained in:
parent
7b3eae3dcb
commit
2f894cb311
@ -4582,29 +4582,3 @@ func TestImageDrawImageAfterDeallocation(t *testing.T) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestUnsyncedPixels(t *testing.T) {
|
||||
// This tests a corner case in internal/buffer.Image.
|
||||
dst := ebiten.NewImage(16, 16)
|
||||
|
||||
// Add an entry for dotsBuffer at (0, 0).
|
||||
dst.Set(0, 0, color.RGBA{0xff, 0xff, 0xff, 0xff})
|
||||
|
||||
// Merge the entry into the cached pixels.
|
||||
// The entry for dotsBuffer is now gone in the current implementation.
|
||||
dst.ReadPixels(make([]byte, 4*16*16))
|
||||
|
||||
// Call WritePixels with the outside region of (0, 0).
|
||||
dst.SubImage(image.Rect(1, 1, 3, 3)).(*ebiten.Image).WritePixels(make([]byte, 4*2*2))
|
||||
|
||||
// Flush unsynced pixel cache.
|
||||
src := ebiten.NewImage(16, 16)
|
||||
dst.DrawImage(src, nil)
|
||||
|
||||
// Check the result is correct.
|
||||
got := dst.At(0, 0)
|
||||
want := color.RGBA{0xff, 0xff, 0xff, 0xff}
|
||||
if got != want {
|
||||
t.Errorf("got: %v, want: %v", got, want)
|
||||
}
|
||||
}
|
||||
|
333
internal/beforemaintest/image_test.go
Normal file
333
internal/beforemaintest/image_test.go
Normal file
@ -0,0 +1,333 @@
|
||||
// Copyright 2019 The Ebiten Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package beforemiantest_test
|
||||
|
||||
import (
|
||||
"image/color"
|
||||
"os"
|
||||
"runtime"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/hajimehoshi/ebiten/v2"
|
||||
"github.com/hajimehoshi/ebiten/v2/internal/atlas"
|
||||
"github.com/hajimehoshi/ebiten/v2/internal/buffered"
|
||||
)
|
||||
|
||||
var gameUpdateCh = make(chan func())
|
||||
|
||||
func runOnGameUpdate(f func()) {
|
||||
ch := make(chan struct{})
|
||||
gameUpdateCh <- func() {
|
||||
f()
|
||||
close(ch)
|
||||
}
|
||||
<-ch
|
||||
}
|
||||
|
||||
type game struct {
|
||||
m *testing.M
|
||||
endCh chan struct{}
|
||||
code int
|
||||
}
|
||||
|
||||
func (g *game) Update() error {
|
||||
select {
|
||||
case f := <-gameUpdateCh:
|
||||
f()
|
||||
case <-g.endCh:
|
||||
return ebiten.Termination
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (*game) Draw(*ebiten.Image) {
|
||||
}
|
||||
|
||||
func (*game) Layout(int, int) (int, int) {
|
||||
return 320, 240
|
||||
}
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
codeCh := make(chan int)
|
||||
endCh := make(chan struct{})
|
||||
go func() {
|
||||
code := m.Run()
|
||||
close(endCh)
|
||||
codeCh <- code
|
||||
close(codeCh)
|
||||
}()
|
||||
|
||||
g := &game{
|
||||
m: m,
|
||||
endCh: endCh,
|
||||
}
|
||||
if err := ebiten.RunGame(g); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
os.Exit(<-codeCh)
|
||||
}
|
||||
|
||||
type testResult struct {
|
||||
want color.RGBA
|
||||
got <-chan color.RGBA
|
||||
}
|
||||
|
||||
var testSetBeforeMainResult = func() testResult {
|
||||
clr := color.RGBA{R: 1, G: 2, B: 3, A: 4}
|
||||
img := ebiten.NewImage(16, 16)
|
||||
img.Set(0, 0, clr)
|
||||
|
||||
ch := make(chan color.RGBA, 1)
|
||||
go func() {
|
||||
runOnGameUpdate(func() {
|
||||
ch <- img.At(0, 0).(color.RGBA)
|
||||
})
|
||||
}()
|
||||
|
||||
return testResult{
|
||||
want: clr,
|
||||
got: ch,
|
||||
}
|
||||
}()
|
||||
|
||||
func TestSetBeforeMain(t *testing.T) {
|
||||
got := <-testSetBeforeMainResult.got
|
||||
want := testSetBeforeMainResult.want
|
||||
|
||||
if got != want {
|
||||
t.Errorf("got: %v, want: %v", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
var testDrawImageBeforeMainResult = func() testResult {
|
||||
const w, h = 16, 16
|
||||
src := ebiten.NewImage(w, h)
|
||||
dst := ebiten.NewImage(w, h)
|
||||
src.Set(0, 0, color.White)
|
||||
dst.DrawImage(src, nil)
|
||||
|
||||
ch := make(chan color.RGBA, 1)
|
||||
go func() {
|
||||
runOnGameUpdate(func() {
|
||||
ch <- dst.At(0, 0).(color.RGBA)
|
||||
})
|
||||
}()
|
||||
|
||||
return testResult{
|
||||
want: color.RGBA{R: 0xff, G: 0xff, B: 0xff, A: 0xff},
|
||||
got: ch,
|
||||
}
|
||||
}()
|
||||
|
||||
func TestDrawImageBeforeMain(t *testing.T) {
|
||||
got := <-testDrawImageBeforeMainResult.got
|
||||
want := testDrawImageBeforeMainResult.want
|
||||
|
||||
if got != want {
|
||||
t.Errorf("got: %v, want: %v", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
var testDrawTrianglesBeforeMainResult = func() testResult {
|
||||
const w, h = 16, 16
|
||||
src := ebiten.NewImage(w, h)
|
||||
dst := ebiten.NewImage(w, h)
|
||||
src.Set(0, 0, color.White)
|
||||
vs := []ebiten.Vertex{
|
||||
{
|
||||
DstX: 0,
|
||||
DstY: 0,
|
||||
SrcX: 0,
|
||||
SrcY: 0,
|
||||
ColorR: 1,
|
||||
ColorG: 1,
|
||||
ColorB: 1,
|
||||
ColorA: 1,
|
||||
},
|
||||
{
|
||||
DstX: w,
|
||||
DstY: 0,
|
||||
SrcX: w,
|
||||
SrcY: 0,
|
||||
ColorR: 1,
|
||||
ColorG: 1,
|
||||
ColorB: 1,
|
||||
ColorA: 1,
|
||||
},
|
||||
{
|
||||
DstX: 0,
|
||||
DstY: h,
|
||||
SrcX: 0,
|
||||
SrcY: h,
|
||||
ColorR: 1,
|
||||
ColorG: 1,
|
||||
ColorB: 1,
|
||||
ColorA: 1,
|
||||
},
|
||||
}
|
||||
dst.DrawTriangles(vs, []uint16{0, 1, 2}, src, nil)
|
||||
|
||||
ch := make(chan color.RGBA, 1)
|
||||
go func() {
|
||||
runOnGameUpdate(func() {
|
||||
ch <- dst.At(0, 0).(color.RGBA)
|
||||
})
|
||||
}()
|
||||
|
||||
return testResult{
|
||||
want: color.RGBA{R: 0xff, G: 0xff, B: 0xff, A: 0xff},
|
||||
got: ch,
|
||||
}
|
||||
}()
|
||||
|
||||
func TestDrawTrianglesBeforeMain(t *testing.T) {
|
||||
got := <-testDrawTrianglesBeforeMainResult.got
|
||||
want := testDrawTrianglesBeforeMainResult.want
|
||||
|
||||
if got != want {
|
||||
t.Errorf("got: %v, want: %v", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
var testSetAndFillBeforeMainResult = func() testResult {
|
||||
clr := color.RGBA{R: 1, G: 2, B: 3, A: 4}
|
||||
img := ebiten.NewImage(16, 16)
|
||||
img.Set(0, 0, clr)
|
||||
img.Fill(color.RGBA{R: 5, G: 6, B: 7, A: 8})
|
||||
img.Set(1, 0, clr)
|
||||
|
||||
ch := make(chan color.RGBA, 1)
|
||||
go func() {
|
||||
runOnGameUpdate(func() {
|
||||
ch <- img.At(0, 0).(color.RGBA)
|
||||
})
|
||||
}()
|
||||
|
||||
return testResult{
|
||||
want: color.RGBA{R: 5, G: 6, B: 7, A: 8},
|
||||
got: ch,
|
||||
}
|
||||
}()
|
||||
|
||||
func TestSetAndFillBeforeMain(t *testing.T) {
|
||||
got := <-testSetAndFillBeforeMainResult.got
|
||||
want := testSetAndFillBeforeMainResult.want
|
||||
|
||||
if got != want {
|
||||
t.Errorf("got: %v, want: %v", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
var testSetAndWritePixelsBeforeMainResult = func() testResult {
|
||||
clr := color.RGBA{R: 1, G: 2, B: 3, A: 4}
|
||||
img := ebiten.NewImage(16, 16)
|
||||
img.Set(0, 0, clr)
|
||||
pix := make([]byte, 4*16*16)
|
||||
for i := 0; i < len(pix)/4; i++ {
|
||||
pix[4*i] = 5
|
||||
pix[4*i+1] = 6
|
||||
pix[4*i+2] = 7
|
||||
pix[4*i+3] = 8
|
||||
}
|
||||
img.WritePixels(pix)
|
||||
img.Set(1, 0, clr)
|
||||
|
||||
ch := make(chan color.RGBA, 1)
|
||||
go func() {
|
||||
runOnGameUpdate(func() {
|
||||
ch <- img.At(0, 0).(color.RGBA)
|
||||
})
|
||||
}()
|
||||
|
||||
return testResult{
|
||||
want: color.RGBA{R: 5, G: 6, B: 7, A: 8},
|
||||
got: ch,
|
||||
}
|
||||
}()
|
||||
|
||||
func TestSetAndWritePixelsBeforeMain(t *testing.T) {
|
||||
got := <-testSetAndWritePixelsBeforeMainResult.got
|
||||
want := testSetAndWritePixelsBeforeMainResult.want
|
||||
|
||||
if got != want {
|
||||
t.Errorf("got: %v, want: %v", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
var testWritePixelsAndModifyBeforeMainResult = func() testResult {
|
||||
img := ebiten.NewImage(16, 16)
|
||||
pix := make([]byte, 4*16*16)
|
||||
for i := 0; i < len(pix)/4; i++ {
|
||||
pix[4*i] = 1
|
||||
pix[4*i+1] = 2
|
||||
pix[4*i+2] = 3
|
||||
pix[4*i+3] = 4
|
||||
}
|
||||
img.WritePixels(pix)
|
||||
// After calling WritePixels, modifying pix must not affect the result.
|
||||
for i := 0; i < len(pix)/4; i++ {
|
||||
pix[4*i] = 5
|
||||
pix[4*i+1] = 6
|
||||
pix[4*i+2] = 7
|
||||
pix[4*i+3] = 8
|
||||
}
|
||||
|
||||
ch := make(chan color.RGBA, 1)
|
||||
go func() {
|
||||
runOnGameUpdate(func() {
|
||||
ch <- img.At(0, 0).(color.RGBA)
|
||||
})
|
||||
}()
|
||||
|
||||
return testResult{
|
||||
want: color.RGBA{R: 1, G: 2, B: 3, A: 4},
|
||||
got: ch,
|
||||
}
|
||||
}()
|
||||
|
||||
func TestWritePixelsAndModifyBeforeMain(t *testing.T) {
|
||||
got := <-testWritePixelsAndModifyBeforeMainResult.got
|
||||
want := testWritePixelsAndModifyBeforeMainResult.want
|
||||
|
||||
if got != want {
|
||||
t.Errorf("got: %v, want: %v", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
var imageGCedCh = make(chan struct{})
|
||||
|
||||
func init() {
|
||||
img := buffered.NewImage(1, 1, atlas.ImageTypeRegular)
|
||||
runtime.SetFinalizer(img, func(*buffered.Image) {
|
||||
close(imageGCedCh)
|
||||
})
|
||||
}
|
||||
|
||||
func TestGC(t *testing.T) {
|
||||
runOnGameUpdate(func() {
|
||||
runtime.GC()
|
||||
|
||||
// A finalizer should be called eventually, but this might not be immediate.
|
||||
// Set a time out.
|
||||
select {
|
||||
case <-imageGCedCh:
|
||||
return
|
||||
case <-time.After(time.Second):
|
||||
t.Error("an image in init() must be GCed but not")
|
||||
}
|
||||
})
|
||||
}
|
@ -146,7 +146,7 @@ func (i *Image) WritePixels(pix []byte, region image.Rectangle) {
|
||||
copy(i.pixels[dstX:dstX+lineWidth], pix[srcX:srcX+lineWidth])
|
||||
}
|
||||
// pixelsUnsynced can NOT be set false as the outside pixels of the region is not written by WritePixels here.
|
||||
// See the test ebiten.TestUnsyncedPixels.
|
||||
// See the test TestUnsyncedPixels.
|
||||
}
|
||||
|
||||
// Even if i.pixels is nil, do not create a pixel cache.
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright 2019 The Ebiten Authors
|
||||
// Copyright 2024 The Ebitengine Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
@ -15,319 +15,48 @@
|
||||
package buffered_test
|
||||
|
||||
import (
|
||||
"image/color"
|
||||
"os"
|
||||
"runtime"
|
||||
"image"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/hajimehoshi/ebiten/v2"
|
||||
"github.com/hajimehoshi/ebiten/v2/internal/atlas"
|
||||
"github.com/hajimehoshi/ebiten/v2/internal/buffered"
|
||||
"github.com/hajimehoshi/ebiten/v2/internal/graphics"
|
||||
"github.com/hajimehoshi/ebiten/v2/internal/graphicsdriver"
|
||||
t "github.com/hajimehoshi/ebiten/v2/internal/testing"
|
||||
"github.com/hajimehoshi/ebiten/v2/internal/ui"
|
||||
)
|
||||
|
||||
var gameUpdateCh = make(chan func())
|
||||
|
||||
func runOnGameUpdate(f func()) {
|
||||
ch := make(chan struct{})
|
||||
gameUpdateCh <- func() {
|
||||
f()
|
||||
close(ch)
|
||||
}
|
||||
<-ch
|
||||
}
|
||||
|
||||
type game struct {
|
||||
m *testing.M
|
||||
endCh chan struct{}
|
||||
code int
|
||||
}
|
||||
|
||||
func (g *game) Update() error {
|
||||
select {
|
||||
case f := <-gameUpdateCh:
|
||||
f()
|
||||
case <-g.endCh:
|
||||
return ebiten.Termination
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (*game) Draw(*ebiten.Image) {
|
||||
}
|
||||
|
||||
func (*game) Layout(int, int) (int, int) {
|
||||
return 320, 240
|
||||
}
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
codeCh := make(chan int)
|
||||
endCh := make(chan struct{})
|
||||
go func() {
|
||||
code := m.Run()
|
||||
close(endCh)
|
||||
codeCh <- code
|
||||
close(codeCh)
|
||||
}()
|
||||
|
||||
g := &game{
|
||||
m: m,
|
||||
endCh: endCh,
|
||||
}
|
||||
if err := ebiten.RunGame(g); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
os.Exit(<-codeCh)
|
||||
t.MainWithRunLoop(m)
|
||||
}
|
||||
|
||||
type testResult struct {
|
||||
want color.RGBA
|
||||
got <-chan color.RGBA
|
||||
}
|
||||
func TestUnsyncedPixels(t *testing.T) {
|
||||
dst := buffered.NewImage(16, 16, atlas.ImageTypeRegular)
|
||||
|
||||
var testSetBeforeMainResult = func() testResult {
|
||||
clr := color.RGBA{R: 1, G: 2, B: 3, A: 4}
|
||||
img := ebiten.NewImage(16, 16)
|
||||
img.Set(0, 0, clr)
|
||||
// Add an entry for dotsBuffer at (0, 0).
|
||||
dst.WritePixels([]byte{0xff, 0xff, 0xff, 0xff}, image.Rect(0, 0, 1, 1))
|
||||
|
||||
ch := make(chan color.RGBA, 1)
|
||||
go func() {
|
||||
runOnGameUpdate(func() {
|
||||
ch <- img.At(0, 0).(color.RGBA)
|
||||
})
|
||||
}()
|
||||
// Merge the entry into the cached pixels.
|
||||
// The entry for dotsBuffer is now gone in the current implementation.
|
||||
dst.ReadPixels(ui.Get().GraphicsDriverForTesting(), make([]byte, 4*16*16), image.Rect(0, 0, 16, 16))
|
||||
|
||||
return testResult{
|
||||
want: clr,
|
||||
got: ch,
|
||||
}
|
||||
}()
|
||||
// Call WritePixels with the outside region of (0, 0).
|
||||
dst.WritePixels(make([]byte, 4*2*2), image.Rect(1, 1, 3, 3))
|
||||
|
||||
func TestSetBeforeMain(t *testing.T) {
|
||||
got := <-testSetBeforeMainResult.got
|
||||
want := testSetBeforeMainResult.want
|
||||
// Flush unsynced pixel cache.
|
||||
src := buffered.NewImage(16, 16, atlas.ImageTypeRegular)
|
||||
vs := make([]float32, 4*graphics.VertexFloatCount)
|
||||
graphics.QuadVertices(vs, 0, 0, 16, 16, 1, 0, 0, 1, 0, 0, 1, 1, 1, 1)
|
||||
is := graphics.QuadIndices()
|
||||
dr := image.Rect(0, 0, 16, 16)
|
||||
sr := [graphics.ShaderImageCount]image.Rectangle{image.Rect(0, 0, 16, 16)}
|
||||
dst.DrawTriangles([graphics.ShaderImageCount]*buffered.Image{src}, vs, is, graphicsdriver.BlendSourceOver, dr, sr, atlas.NearestFilterShader, nil, graphicsdriver.FillAll)
|
||||
|
||||
// Check the result is correct.
|
||||
var got [4]byte
|
||||
dst.ReadPixels(ui.Get().GraphicsDriverForTesting(), got[:], image.Rect(0, 0, 1, 1))
|
||||
want := [4]byte{0xff, 0xff, 0xff, 0xff}
|
||||
if got != want {
|
||||
t.Errorf("got: %v, want: %v", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
var testDrawImageBeforeMainResult = func() testResult {
|
||||
const w, h = 16, 16
|
||||
src := ebiten.NewImage(w, h)
|
||||
dst := ebiten.NewImage(w, h)
|
||||
src.Set(0, 0, color.White)
|
||||
dst.DrawImage(src, nil)
|
||||
|
||||
ch := make(chan color.RGBA, 1)
|
||||
go func() {
|
||||
runOnGameUpdate(func() {
|
||||
ch <- dst.At(0, 0).(color.RGBA)
|
||||
})
|
||||
}()
|
||||
|
||||
return testResult{
|
||||
want: color.RGBA{R: 0xff, G: 0xff, B: 0xff, A: 0xff},
|
||||
got: ch,
|
||||
}
|
||||
}()
|
||||
|
||||
func TestDrawImageBeforeMain(t *testing.T) {
|
||||
got := <-testDrawImageBeforeMainResult.got
|
||||
want := testDrawImageBeforeMainResult.want
|
||||
|
||||
if got != want {
|
||||
t.Errorf("got: %v, want: %v", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
var testDrawTrianglesBeforeMainResult = func() testResult {
|
||||
const w, h = 16, 16
|
||||
src := ebiten.NewImage(w, h)
|
||||
dst := ebiten.NewImage(w, h)
|
||||
src.Set(0, 0, color.White)
|
||||
vs := []ebiten.Vertex{
|
||||
{
|
||||
DstX: 0,
|
||||
DstY: 0,
|
||||
SrcX: 0,
|
||||
SrcY: 0,
|
||||
ColorR: 1,
|
||||
ColorG: 1,
|
||||
ColorB: 1,
|
||||
ColorA: 1,
|
||||
},
|
||||
{
|
||||
DstX: w,
|
||||
DstY: 0,
|
||||
SrcX: w,
|
||||
SrcY: 0,
|
||||
ColorR: 1,
|
||||
ColorG: 1,
|
||||
ColorB: 1,
|
||||
ColorA: 1,
|
||||
},
|
||||
{
|
||||
DstX: 0,
|
||||
DstY: h,
|
||||
SrcX: 0,
|
||||
SrcY: h,
|
||||
ColorR: 1,
|
||||
ColorG: 1,
|
||||
ColorB: 1,
|
||||
ColorA: 1,
|
||||
},
|
||||
}
|
||||
dst.DrawTriangles(vs, []uint16{0, 1, 2}, src, nil)
|
||||
|
||||
ch := make(chan color.RGBA, 1)
|
||||
go func() {
|
||||
runOnGameUpdate(func() {
|
||||
ch <- dst.At(0, 0).(color.RGBA)
|
||||
})
|
||||
}()
|
||||
|
||||
return testResult{
|
||||
want: color.RGBA{R: 0xff, G: 0xff, B: 0xff, A: 0xff},
|
||||
got: ch,
|
||||
}
|
||||
}()
|
||||
|
||||
func TestDrawTrianglesBeforeMain(t *testing.T) {
|
||||
got := <-testDrawTrianglesBeforeMainResult.got
|
||||
want := testDrawTrianglesBeforeMainResult.want
|
||||
|
||||
if got != want {
|
||||
t.Errorf("got: %v, want: %v", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
var testSetAndFillBeforeMainResult = func() testResult {
|
||||
clr := color.RGBA{R: 1, G: 2, B: 3, A: 4}
|
||||
img := ebiten.NewImage(16, 16)
|
||||
img.Set(0, 0, clr)
|
||||
img.Fill(color.RGBA{R: 5, G: 6, B: 7, A: 8})
|
||||
img.Set(1, 0, clr)
|
||||
|
||||
ch := make(chan color.RGBA, 1)
|
||||
go func() {
|
||||
runOnGameUpdate(func() {
|
||||
ch <- img.At(0, 0).(color.RGBA)
|
||||
})
|
||||
}()
|
||||
|
||||
return testResult{
|
||||
want: color.RGBA{R: 5, G: 6, B: 7, A: 8},
|
||||
got: ch,
|
||||
}
|
||||
}()
|
||||
|
||||
func TestSetAndFillBeforeMain(t *testing.T) {
|
||||
got := <-testSetAndFillBeforeMainResult.got
|
||||
want := testSetAndFillBeforeMainResult.want
|
||||
|
||||
if got != want {
|
||||
t.Errorf("got: %v, want: %v", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
var testSetAndWritePixelsBeforeMainResult = func() testResult {
|
||||
clr := color.RGBA{R: 1, G: 2, B: 3, A: 4}
|
||||
img := ebiten.NewImage(16, 16)
|
||||
img.Set(0, 0, clr)
|
||||
pix := make([]byte, 4*16*16)
|
||||
for i := 0; i < len(pix)/4; i++ {
|
||||
pix[4*i] = 5
|
||||
pix[4*i+1] = 6
|
||||
pix[4*i+2] = 7
|
||||
pix[4*i+3] = 8
|
||||
}
|
||||
img.WritePixels(pix)
|
||||
img.Set(1, 0, clr)
|
||||
|
||||
ch := make(chan color.RGBA, 1)
|
||||
go func() {
|
||||
runOnGameUpdate(func() {
|
||||
ch <- img.At(0, 0).(color.RGBA)
|
||||
})
|
||||
}()
|
||||
|
||||
return testResult{
|
||||
want: color.RGBA{R: 5, G: 6, B: 7, A: 8},
|
||||
got: ch,
|
||||
}
|
||||
}()
|
||||
|
||||
func TestSetAndWritePixelsBeforeMain(t *testing.T) {
|
||||
got := <-testSetAndWritePixelsBeforeMainResult.got
|
||||
want := testSetAndWritePixelsBeforeMainResult.want
|
||||
|
||||
if got != want {
|
||||
t.Errorf("got: %v, want: %v", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
var testWritePixelsAndModifyBeforeMainResult = func() testResult {
|
||||
img := ebiten.NewImage(16, 16)
|
||||
pix := make([]byte, 4*16*16)
|
||||
for i := 0; i < len(pix)/4; i++ {
|
||||
pix[4*i] = 1
|
||||
pix[4*i+1] = 2
|
||||
pix[4*i+2] = 3
|
||||
pix[4*i+3] = 4
|
||||
}
|
||||
img.WritePixels(pix)
|
||||
// After calling WritePixels, modifying pix must not affect the result.
|
||||
for i := 0; i < len(pix)/4; i++ {
|
||||
pix[4*i] = 5
|
||||
pix[4*i+1] = 6
|
||||
pix[4*i+2] = 7
|
||||
pix[4*i+3] = 8
|
||||
}
|
||||
|
||||
ch := make(chan color.RGBA, 1)
|
||||
go func() {
|
||||
runOnGameUpdate(func() {
|
||||
ch <- img.At(0, 0).(color.RGBA)
|
||||
})
|
||||
}()
|
||||
|
||||
return testResult{
|
||||
want: color.RGBA{R: 1, G: 2, B: 3, A: 4},
|
||||
got: ch,
|
||||
}
|
||||
}()
|
||||
|
||||
func TestWritePixelsAndModifyBeforeMain(t *testing.T) {
|
||||
got := <-testWritePixelsAndModifyBeforeMainResult.got
|
||||
want := testWritePixelsAndModifyBeforeMainResult.want
|
||||
|
||||
if got != want {
|
||||
t.Errorf("got: %v, want: %v", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
var imageGCedCh = make(chan struct{})
|
||||
|
||||
func init() {
|
||||
img := buffered.NewImage(1, 1, atlas.ImageTypeRegular)
|
||||
runtime.SetFinalizer(img, func(*buffered.Image) {
|
||||
close(imageGCedCh)
|
||||
})
|
||||
}
|
||||
|
||||
func TestGC(t *testing.T) {
|
||||
runOnGameUpdate(func() {
|
||||
runtime.GC()
|
||||
|
||||
// A finalizer should be called eventually, but this might not be immediate.
|
||||
// Set a time out.
|
||||
select {
|
||||
case <-imageGCedCh:
|
||||
return
|
||||
case <-time.After(time.Second):
|
||||
t.Error("an image in init() must be GCed but not")
|
||||
}
|
||||
})
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user