github.com/o1egl/govatar@v0.4.1/govatar_test.go (about)

     1  package govatar
     2  
     3  import (
     4  	"image"
     5  	"image/color"
     6  	"math/rand"
     7  	"net/http"
     8  	"os"
     9  	"testing"
    10  
    11  	"github.com/stretchr/testify/assert"
    12  )
    13  
    14  func TestGenerate(t *testing.T) {
    15  	testCases := map[string]struct {
    16  		gender Gender
    17  		err    error
    18  	}{
    19  		"male": {
    20  			gender: MALE,
    21  		},
    22  		"female": {
    23  			gender: FEMALE,
    24  		},
    25  		"unsupported": {
    26  			gender: Gender(-1),
    27  			err:    ErrUnsupportedGender,
    28  		},
    29  	}
    30  
    31  	for name, test := range testCases {
    32  		t.Run(name, func(t *testing.T) {
    33  			avatar, err := Generate(test.gender)
    34  			assert.Equal(t, test.err, err)
    35  			if test.err == nil && assert.NotNil(t, avatar) {
    36  				bounds := avatar.Bounds()
    37  				if assert.False(t, bounds.Empty()) {
    38  					assert.Equal(t, 400, bounds.Dx())
    39  					assert.Equal(t, 400, bounds.Dy())
    40  				}
    41  			}
    42  		})
    43  	}
    44  }
    45  
    46  var letterRunes = []rune("abcdefghijklmnopqrstuvwxyz")
    47  
    48  func randStringRunes(n int) string {
    49  	b := make([]rune, n)
    50  	for i := range b {
    51  		b[i] = letterRunes[rand.Intn(len(letterRunes))]
    52  	}
    53  	return string(b)
    54  }
    55  
    56  func TestGenerateFile(t *testing.T) {
    57  	fileName := randStringRunes(6)
    58  	testCases := map[string]struct {
    59  		imageName string
    60  		mimeType  string
    61  	}{
    62  		"jpeg": {imageName: fileName + ".jpeg", mimeType: "image/jpeg"},
    63  		"jpg":  {imageName: fileName + ".jpg", mimeType: "image/jpeg"},
    64  		"png":  {imageName: fileName + ".png", mimeType: "image/png"},
    65  		"gif":  {imageName: fileName + ".gif", mimeType: "image/gif"},
    66  		"xyz":  {imageName: fileName + ".xyz", mimeType: "image/png"},
    67  	}
    68  
    69  	for name, test := range testCases {
    70  		t.Run(name, func(t *testing.T) {
    71  			os.Remove(test.imageName)
    72  			defer os.Remove(test.imageName)
    73  			err := GenerateFile(MALE, test.imageName)
    74  			if assert.NoError(t, err) {
    75  				buf := make([]byte, 512)
    76  				f, err := os.Open(test.imageName)
    77  				if assert.NoError(t, err) {
    78  					defer f.Close()
    79  
    80  					_, err = f.Read(buf)
    81  					if assert.NoError(t, err) {
    82  						assert.Equal(t, test.mimeType, http.DetectContentType(buf))
    83  					}
    84  				}
    85  			}
    86  		})
    87  	}
    88  }
    89  
    90  func TestGenerateFromString(t *testing.T) {
    91  	testCases := map[string]struct {
    92  		gender    Gender
    93  		areEqual  bool
    94  		username1 string
    95  		username2 string
    96  		err       error
    97  	}{
    98  		"equal": {
    99  			gender:    MALE,
   100  			areEqual:  true,
   101  			username1: "username@site.com",
   102  			username2: "username@site.com",
   103  		},
   104  		"not equal": {
   105  			gender:    MALE,
   106  			areEqual:  false,
   107  			username1: "username@site.com",
   108  			username2: "another-username@site.com",
   109  		},
   110  		"error": {
   111  			gender:    Gender(-1),
   112  			username1: "username@site.com",
   113  			username2: "username@site.com",
   114  			err:       ErrUnsupportedGender,
   115  		},
   116  	}
   117  
   118  	for name, test := range testCases {
   119  		t.Run(name, func(t *testing.T) {
   120  			avatar1, err := GenerateForUsername(test.gender, test.username1)
   121  			assert.Equal(t, test.err, err)
   122  			if test.err == nil && assert.NotNil(t, avatar1) {
   123  				bounds := avatar1.Bounds()
   124  				assert.False(t, bounds.Empty())
   125  				assert.Equal(t, 400, bounds.Dx())
   126  				assert.Equal(t, 400, bounds.Dy())
   127  
   128  				avatar2, err := GenerateForUsername(test.gender, test.username2)
   129  				if assert.NoError(t, err) {
   130  					assert.Equal(t, test.areEqual, areImagesEqual(avatar1, avatar2))
   131  				}
   132  			}
   133  		})
   134  	}
   135  
   136  }
   137  
   138  func TestGenerateFileFromString(t *testing.T) {
   139  	fileName := randStringRunes(6)
   140  	testCases := map[string]struct {
   141  		imageName string
   142  		mimeType  string
   143  	}{
   144  		"jpeg": {imageName: fileName + ".jpeg", mimeType: "image/jpeg"},
   145  		"jpg":  {imageName: fileName + ".jpg", mimeType: "image/jpeg"},
   146  		"png":  {imageName: fileName + ".png", mimeType: "image/png"},
   147  		"gif":  {imageName: fileName + ".gif", mimeType: "image/gif"},
   148  		"xyz":  {imageName: fileName + ".xyz", mimeType: "image/png"},
   149  	}
   150  
   151  	for name, test := range testCases {
   152  		t.Run(name, func(t *testing.T) {
   153  			os.Remove(test.imageName)
   154  			defer os.Remove(test.imageName)
   155  			err := GenerateFileForUsername(MALE, "username@site.com", test.imageName)
   156  			if assert.NoError(t, err) {
   157  				buf := make([]byte, 512)
   158  				f, err := os.Open(test.imageName)
   159  				if assert.NoError(t, err) {
   160  					defer f.Close()
   161  
   162  					_, err = f.Read(buf)
   163  					if assert.NoError(t, err) {
   164  						assert.Equal(t, test.mimeType, http.DetectContentType(buf))
   165  					}
   166  				}
   167  			}
   168  		})
   169  	}
   170  }
   171  
   172  func areImagesEqual(a, b image.Image) bool {
   173  	ab, bb := a.Bounds(), b.Bounds()
   174  	w, h := ab.Dx(), ab.Dy()
   175  	if w != bb.Dx() || h != bb.Dy() {
   176  		return false
   177  	}
   178  	n := 0
   179  	for y := 0; y < h; y++ {
   180  		for x := 0; x < w; x++ {
   181  			d := diffColor(a.At(ab.Min.X+x, ab.Min.Y+y), b.At(bb.Min.X+x, bb.Min.Y+y))
   182  			c := color.RGBA{0, 0, 0, 0xff}
   183  			if d > 0 {
   184  				c.R = 0xff
   185  				n++
   186  			}
   187  		}
   188  	}
   189  	return n == 0
   190  }
   191  
   192  func diffColor(c1, c2 color.Color) int64 {
   193  	r1, g1, b1, a1 := c1.RGBA()
   194  	r2, g2, b2, a2 := c2.RGBA()
   195  	var diff int64
   196  	diff += abs(int64(r1) - int64(r2))
   197  	diff += abs(int64(g1) - int64(g2))
   198  	diff += abs(int64(b1) - int64(b2))
   199  	diff += abs(int64(a1) - int64(a2))
   200  	return diff
   201  }
   202  
   203  func abs(x int64) int64 {
   204  	if x < 0 {
   205  		return -x
   206  	}
   207  	return x
   208  }