|  | package parse | 
|  |  | 
|  | import ( | 
|  | "testing" | 
|  |  | 
|  | "github.com/stretchr/testify/assert" | 
|  | ) | 
|  |  | 
|  | const goodSample = `// Copyright 2019 Google LLC. | 
|  | // Use of this source code is governed by a BSD-style license that can be found in the LICENSE file. | 
|  | #include "fiddle/examples.h" | 
|  | // HASH=bc9c7ea424d10bbcd1e5a88770d4794e | 
|  | REG_FIDDLE(Alpha_Constants_a, 400, 600, true, 2) { | 
|  | void draw(SkCanvas* canvas) { | 
|  | std::vector<int32_t> srcPixels; | 
|  | srcPixels.resize(source.height() * source.rowBytes()); | 
|  | SkPixmap pixmap(SkImageInfo::MakeN32Premul(source.width(), source.height()), | 
|  | &srcPixels.front(), source.rowBytes()); | 
|  | source.readPixels(pixmap, 0, 0); | 
|  | for (int y = 0; y < 16; ++y) { | 
|  | for (int x = 0; x < 16; ++x) { | 
|  | int32_t* blockStart = &srcPixels.front() + y * source.width() * 16 + x * 16; | 
|  | size_t transparentCount = 0; | 
|  | for (int fillY = 0; fillY < source.height() / 16; ++fillY) { | 
|  | for (int fillX = 0; fillX < source.width() / 16; ++fillX) { | 
|  | const SkColor color = SkUnPreMultiply::PMColorToColor(blockStart[fillX]); | 
|  | transparentCount += SkColorGetA(color) == SK_AlphaTRANSPARENT; | 
|  | } | 
|  | blockStart += source.width(); | 
|  | } | 
|  | if (transparentCount > 200) { | 
|  | blockStart = &srcPixels.front() + y * source.width() * 16 + x * 16; | 
|  | for (int fillY = 0; fillY < source.height() / 16; ++fillY) { | 
|  | for (int fillX = 0; fillX < source.width() / 16; ++fillX) { | 
|  | blockStart[fillX] = SK_ColorRED; | 
|  | } | 
|  | blockStart += source.width(); | 
|  | } | 
|  | } | 
|  | } | 
|  | } | 
|  | SkBitmap bitmap; | 
|  | bitmap.installPixels(pixmap); | 
|  | canvas->drawBitmap(bitmap, 0, 0); | 
|  | } | 
|  | }  // END FIDDLE` | 
|  |  | 
|  | const shortSample = `// Copyright 2019 Google LLC. | 
|  | REG_FIDDLE(EmptyFiddle, 256, 128, false, 1) { | 
|  | void draw(SkCanvas* canvas) { | 
|  | } | 
|  | }  // END FIDDLE` | 
|  |  | 
|  | const missingEndSample = `// Copyright 2019 Google LLC. | 
|  | REG_FIDDLE(Alpha_Constants_a, 256, 128, false, 1) { | 
|  | void draw(SkCanvas* canvas) { | 
|  | } | 
|  | }` | 
|  |  | 
|  | const inactiveSample = `#if 0  // Disabled until updated to use current API. | 
|  | // Copyright 2019 Google LLC. | 
|  | // Use of this source code is governed by a BSD-style license that can be found in the LICENSE file. | 
|  | #include "fiddle/examples.h" | 
|  | // HASH=f0e584aec20eaee7a5bfed62aa885eee | 
|  | REG_FIDDLE(TextBlobBuilder_allocRun, 256, 60, false, 0) { | 
|  | void draw(SkCanvas* canvas) { | 
|  | SkTextBlobBuilder builder; | 
|  | SkFont font; | 
|  | SkPaint paint; | 
|  | const SkTextBlobBuilder::RunBuffer& run = builder.allocRun(font, 5, 20, 20); | 
|  | paint.textToGlyphs("hello", 5, run.glyphs); | 
|  | canvas->drawRect({20, 20, 30, 30}, paint); | 
|  | canvas->drawTextBlob(builder.make(), 20, 20, paint); | 
|  | } | 
|  | }  // END FIDDLE | 
|  | #endif  // Disabled until updated to use current API.` | 
|  |  | 
|  | const missingRegSample = ` | 
|  | // Copyright 2019 Google LLC. | 
|  | // Use of this source code is governed by a BSD-style license that can be found in the LICENSE file. | 
|  | void draw(SkCanvas* canvas) { | 
|  | SkTextBlobBuilder builder; | 
|  | SkFont font; | 
|  | SkPaint paint; | 
|  | const SkTextBlobBuilder::RunBuffer& run = builder.allocRun(font, 5, 20, 20); | 
|  | paint.textToGlyphs("hello", 5, run.glyphs); | 
|  | canvas->drawRect({20, 20, 30, 30}, paint); | 
|  | canvas->drawTextBlob(builder.make(), 20, 20, paint); | 
|  | } | 
|  | }  // END FIDDLE` | 
|  |  | 
|  | const badMacro = `REG_FIDDLE(TextBlobBuilder_allocRun, foo, 60, false, 0) {` | 
|  |  | 
|  | const textonlySample = `// Copyright 2019 Google LLC. | 
|  | REG_FIDDLE(50_percent_gray, 256, 128, true, 0) { | 
|  | void draw(SkCanvas* canvas) { | 
|  | } | 
|  | }  // END FIDDLE` | 
|  |  | 
|  | const animatedSample = `// Copyright 2020 Google LLC. | 
|  | // Use of this source code is governed by a BSD-style license that can be found in the LICENSE file. | 
|  | #include "tools/fiddle/examples.h" | 
|  | REG_FIDDLE_ANIMATED(pong, 256, 300, false, 0, 10.5) { | 
|  | static SkScalar PingPong(double t, SkScalar period, SkScalar phase, | 
|  | SkScalar ends, SkScalar mid) { | 
|  | double value = ::fmod(t + phase, period); | 
|  | double half = period / 2.0; | 
|  | double diff = ::fabs(value - half); | 
|  | return SkDoubleToScalar(ends + (1.0 - diff / half) * (mid - ends)); | 
|  | } | 
|  |  | 
|  | void draw(SkCanvas* canvas) { | 
|  | canvas->clear(SK_ColorBLACK); | 
|  | float ballX = PingPong(frame * duration, 2.5f, 0.0f, 0.0f, 1.0f); | 
|  | float ballY = PingPong(frame * duration, 2.0f, 0.4f, 0.0f, 1.0f); | 
|  |  | 
|  | SkPaint p; | 
|  | p.setColor(SK_ColorWHITE); | 
|  | p.setAntiAlias(true); | 
|  |  | 
|  | float bX = ballX * 472 + 20; | 
|  | float bY = ballY * 200 + 28; | 
|  |  | 
|  | if (canvas->recordingContext()) { | 
|  | canvas->drawRect(SkRect::MakeXYWH(236, bY - 15, 10, 30), p); | 
|  | bX -= 256; | 
|  | } else { | 
|  | canvas->drawRect(SkRect::MakeXYWH(10, bY - 15, 10, 30), p); | 
|  | } | 
|  | canvas->drawCircle(bX, bY, 5, p); | 
|  | } | 
|  | }  // END FIDDLE` | 
|  |  | 
|  | const srgbSample = `// Copyright 2020 Google LLC. | 
|  | // Use of this source code is governed by a BSD-style license that can be found in the LICENSE file. | 
|  | #include "tools/fiddle/examples.h" | 
|  | REG_FIDDLE_SRGB(50_percent_gray, 530, 150, true, 0, 18.5, true) { | 
|  | static sk_sp<SkShader> make_bw_dither() { | 
|  | auto surf = SkSurface::MakeRasterN32Premul(2, 2); | 
|  | surf->getCanvas()->drawColor(SK_ColorWHITE); | 
|  | surf->getCanvas()->drawRect({0, 0, 1, 1}, SkPaint()); | 
|  | surf->getCanvas()->drawRect({1, 1, 2, 2}, SkPaint()); | 
|  | return surf->makeImageSnapshot()->makeShader(SkTileMode::kRepeat, | 
|  | SkTileMode::kRepeat, | 
|  | SkSamplingOptions(SkFilterMode::kLinear)); | 
|  | } | 
|  |  | 
|  | void draw(SkCanvas* canvas) { | 
|  | canvas->drawColor(SK_ColorWHITE); | 
|  | SkFont font(nullptr, 12); | 
|  |  | 
|  | // BW Dither | 
|  | canvas->translate(5, 5); | 
|  | SkPaint p; | 
|  | p.setShader(make_bw_dither()); | 
|  | canvas->drawRect({0, 0, 100, 100}, p); | 
|  | SkPaint black; | 
|  | canvas->drawString("BW Dither", 0, 125, font, black); | 
|  | } | 
|  | }  // END FIDDLE` | 
|  |  | 
|  | func TestParse_ValidSamples_InformationExtracted(t *testing.T) { | 
|  |  | 
|  | fc, err := ParseCpp(goodSample) | 
|  | assert.NoError(t, err) | 
|  | assert.Equal(t, "Alpha_Constants_a", fc.Name) | 
|  | assert.Equal(t, 400, fc.Options.Width) | 
|  | assert.Equal(t, 600, fc.Options.Height) | 
|  | assert.Equal(t, 2, fc.Options.Source) | 
|  | assert.True(t, fc.Options.TextOnly) | 
|  |  | 
|  | fc, err = ParseCpp(shortSample) | 
|  | assert.NoError(t, err) | 
|  | assert.Equal(t, "EmptyFiddle", fc.Name) | 
|  | assert.Equal(t, "void draw(SkCanvas* canvas) {\n}", fc.Code) | 
|  | assert.Equal(t, 256, fc.Options.Width) | 
|  | assert.Equal(t, 128, fc.Options.Height) | 
|  | assert.Equal(t, 1, fc.Options.Source) | 
|  | assert.False(t, fc.Options.TextOnly) | 
|  |  | 
|  | fc, err = ParseCpp(textonlySample) | 
|  | assert.NoError(t, err) | 
|  | assert.Equal(t, "50_percent_gray", fc.Name) | 
|  | assert.Equal(t, "void draw(SkCanvas* canvas) {\n}", fc.Code) | 
|  | assert.Equal(t, 256, fc.Options.Width) | 
|  | assert.Equal(t, 128, fc.Options.Height) | 
|  | assert.Equal(t, 0, fc.Options.Source) | 
|  | assert.True(t, fc.Options.TextOnly) | 
|  | } | 
|  |  | 
|  | func TestParse_AnimatedSample_InformationExtracted(t *testing.T) { | 
|  |  | 
|  | fc, err := ParseCpp(animatedSample) | 
|  | assert.NoError(t, err) | 
|  | assert.Equal(t, "pong", fc.Name) | 
|  | assert.Equal(t, 256, fc.Options.Width) | 
|  | assert.Equal(t, 300, fc.Options.Height) | 
|  | assert.Equal(t, 0, fc.Options.Source) | 
|  | assert.False(t, fc.Options.TextOnly) | 
|  | assert.True(t, fc.Options.Animated) | 
|  | assert.Equal(t, 10.5, fc.Options.Duration) | 
|  | } | 
|  |  | 
|  | func TestParse_SRGBSample_InformationExtracted(t *testing.T) { | 
|  |  | 
|  | fc, err := ParseCpp(srgbSample) | 
|  | assert.NoError(t, err) | 
|  | assert.Equal(t, "50_percent_gray", fc.Name) | 
|  | assert.Equal(t, 530, fc.Options.Width) | 
|  | assert.Equal(t, 150, fc.Options.Height) | 
|  | assert.Equal(t, 0, fc.Options.Source) | 
|  | assert.True(t, fc.Options.TextOnly) | 
|  | assert.True(t, fc.Options.Animated) | 
|  | assert.Equal(t, 18.5, fc.Options.Duration) | 
|  | assert.True(t, fc.Options.F16) | 
|  | assert.True(t, fc.Options.SRGB) | 
|  | } | 
|  |  | 
|  | func TestParse_MissingEndFiddle_ReturnsError(t *testing.T) { | 
|  | _, err := ParseCpp(missingEndSample) | 
|  | assert.Error(t, err) | 
|  | assert.Contains(t, err.Error(), "END FIDDLE") | 
|  | } | 
|  |  | 
|  | func TestParse_FiddleIfDeffedOut_ReturnsError(t *testing.T) { | 
|  | _, err := ParseCpp(inactiveSample) | 
|  | assert.Equal(t, err, ErrorInactiveExample) | 
|  | } | 
|  |  | 
|  | func TestParse_MissingRegFiddle_ReturnsError(t *testing.T) { | 
|  | _, err := ParseCpp(missingRegSample) | 
|  | assert.Error(t, err) | 
|  | assert.Contains(t, err.Error(), "failed to find any REG_FIDDLE*") | 
|  | } | 
|  |  | 
|  | func TestParse_MacroBadWidthParam_ReturnsError(t *testing.T) { | 
|  | _, err := ParseCpp(badMacro) | 
|  | assert.Error(t, err) | 
|  | assert.Contains(t, err.Error(), "parsing width") | 
|  | } |