-
Notifications
You must be signed in to change notification settings - Fork 157
Design Doc: Fully Shared PSOL System Tests
Fully Shared PSOL System Tests
Jeff Kaufman, 2013-03-04
System tests that run on mod_pagespeed, ngx_pagespeed, and any other ports we may do.
When you write a new feature you write unit tests. Those tests work everywhere. This is good. You also write system tests. Unless those system tests are simple enough to work in system_test.sh, which most aren’t, you have to write different tests for automatic and mod_pagespeed. Which is already annoying, but add ngx_pagespeed and it becomes impractical.
It’s also frustrating working with the current test environment. Not only do you have to write bash but tests all run sequentially in shared state. When a test fails you can’t re-run just that test, and crafting a reproducible stand-alone test case is a pain. Most of our tests could run in parallel, but the shell script doesn’t make that practical. And if a global variable, for example http_proxy, gets set wrong somewhere it can be a lot of work to track down what happened.
The logic for a test is also currently split up over many places. There’s the test code in apache_system_test.sh but then there’s pagespeed configuration, origin server configuration, and raw files on the origin server.
Let’s have system tests where the code for a test is all in one place, they work across all of the servers we support, and we don’t have to write in shell.
A test would look like this:
class UrlValuedAttributeTest(psoltest.SystemTest):
"""Verify dynamically defined url-valued attributes are respected.
Test to make sure dynamically defined url-valued attributes are
rewritten by rewrite_domains. See
mod_pagespeed_test/rewrite_domains.html: in addition to having one
<img> URL, one <form> URL, and one <a> url it also has one
<span src=...> URL, one <hr imgsrc=...> URL, and one <hr src=...>
URL, all referencing src.example.com. The first three should be
rewritten because of hardcoded rules, the span.src and hr.imgsrc
should be rewritten because of ModPagespeedUrlValuedAttribute
directives, and the hr.src should be left unmodified. The rewritten
ones should all be rewritten to dst.example.com.
"""
def Configure(self):
self.server = self.NewServer(
"url_attribute.example.com",
pagespeed="""
# Don't actually try to rewrite any resources; the ones in
# rewrite_domains.html don't actually exist.
RewriteLevel PassThrough
# This is used for testing dynamically defined url-valued
# attributes
UrlValuedAttribute span src Hyperlink
UrlValuedAttribute hr imgsrc Image
DomainRewriteHyperlinks on
MapRewriteDomain http://dst.example.com http://src.example.com
EnableFilters rewrite_domains
UrlValuedAttribute custom a Image
UrlValuedAttribute custom b otherResource
UrlValuedAttribute custom c hyperlink
""")
def TestDomainsRewritten(self):
def DomainsRewritten(response):
return response.body.count("http://dst.example.com")) == 5
self.server.FetchUntil("rewrite_domains.html", DomainsRewritten)
def TestPagespeedResourcesCreated(self):
# There are five resources that should be optimized
def ResourcesRewritten(response):
return response.body.count(".pagespeed.") == 5
# Make sure <custom d=...> isn't modified at all, but that everything
# else is recognized as a url and rewritten from ../foo to /foo. This
# means that only one reference to ../mod_pagespeed should remain,
# <custom d=...>.
def CustomDNotModified(response):
return len(re.findall("d=.[.][.]/mod_pa", response.body)) == 1
def OnlyOneRelativeUrlLeft(response):
return response.body.count("../mod_pa") == 1
# There are five images that should be optimized.
def AllImagesOptimized(response):
return response.body.count(".pagespeed.ic") == 5
self.server.FetchUntil("url_valued_attribute_extend_cache.html"
"?ModPagespeedFilters=core,+left_trim_urls",
ResourcesRewritten,
CustomDNotModified,
OnlyOneRelativeUrlLeft,
AllImagesOptimized)
This replaces:
debug.conf.template:
...
<VirtualHost localhost:@@APACHE_SECONDARY_PORT@@>
ServerName url_attribute.example.com
DocumentRoot "@@APACHE_DOC_ROOT@@"
ModPagespeedFileCachePath "@@MOD_PAGESPEED_CACHE@@/"
# Don't actually try to rewrite any resources; the ones in
# rewrite_domains.html don't actually exist.
ModPagespeedRewriteLevel PassThrough
# This is used for testing dynamically defined url-valued
# attributes
ModPagespeedUrlValuedAttribute span src Hyperlink
ModPagespeedUrlValuedAttribute hr imgsrc Image
ModPagespeedDomainRewriteHyperlinks on
ModPagespeedMapRewriteDomain http://dst.example.com http://src.example.com
ModPagespeedEnableFilters rewrite_domains
ModPagespeedUrlValuedAttribute custom a Image
ModPagespeedUrlValuedAttribute custom b otherResource
ModPagespeedUrlValuedAttribute custom c hyperlink
</VirtualHost>
...
apache_system_test.sh:
...
# Test to make sure dynamically defined url-valued attributes are rewritten
# by rewrite_domains. See mod_pagespeed_test/rewrite_domains.html: in
# addition to having one <img> URL, one <form> URL, and one <a> url it also
# has one <span src=...> URL, one <hr imgsrc=...> URL, and one <hr src=...>
# URL, all referencing src.example.com. The first three should be rewritten
# because of hardcoded rules, the span.src and hr.imgsrc should be rewritten
# because of ModPagespeedUrlValuedAttribute directives, and the hr.src
# should be left unmodified. The rewritten ones should all be rewritten to
# dst.example.com.
HOST_NAME="http://url_attribute.example.com"
TEST="$HOST_NAME/mod_pagespeed_test"
REWRITE_DOMAINS="$TEST/rewrite_domains.html"
UVA_EXTEND_CACHE="$TEST/url_valued_attribute_extend_cache.html"
UVA_EXTEND_CACHE+="?ModPagespeedFilters=core,+left_trim_urls"
start_test Rewrite domains in dynamically defined url-valued attributes.
RESPONSE_OUT=$(http_proxy=$SECONDARY_HOSTNAME $WGET_DUMP $REWRITE_DOMAINS)
MATCHES=$(echo "$RESPONSE_OUT" | fgrep -c http://dst.example.com)
check [ $MATCHES -eq 5 ]
MATCHES=$(echo "$RESPONSE_OUT" | \
fgrep -c '<hr src=http://src.example.com/hr-image>')
check [ $MATCHES -eq 1 ]
start_test Additional url-valued attributes are fully respected.
# There are five resources that should be optimized
http_proxy=$SECONDARY_HOSTNAME \
FetchUntil $UVA_EXTEND_CACHE 'fgrep -c .pagespeed.' 5
# Make sure <custom d=...> isn't modified at all, but that everything else
# is recognized as a url and rewritten from ../foo to /foo. This means that
# only one reference to ../mod_pagespeed should remain, <custom d=...>.
http_proxy=$SECONDARY_HOSTNAME \
FetchUntil $UVA_EXTEND_CACHE 'grep -c d=.[.][.]/mod_pa' 1
http_proxy=$SECONDARY_HOSTNAME \
FetchUntil $UVA_EXTEND_CACHE 'fgrep -c ../mod_pa' 1
# There are five images that should be optimized.
http_proxy=$SECONDARY_HOSTNAME \
FetchUntil $UVA_EXTEND_CACHE 'fgrep -c .pagespeed.ic' 5
And generates the following configurations:
apache:
<VirtualHost localhost:8083>
ServerName url_attribute.example.com
DocumentRoot "/path/to/htdocs"
ModPagespeedFileCachePath "/path/to/pagespeed_cache/"
# Don't actually try to rewrite any resources; the ones in
# rewrite_domains.html don't actually exist.
ModPagespeedRewriteLevel PassThrough
# This is used for testing dynamically defined url-valued
# attributes
ModPagespeedUrlValuedAttribute span src Hyperlink
ModPagespeedUrlValuedAttribute hr imgsrc Image
ModPagespeedDomainRewriteHyperlinks on
ModPagespeedMapRewriteDomain http://dst.example.com http://src.example.com
ModPagespeedEnableFilters rewrite_domains
ModPagespeedUrlValuedAttribute custom a Image
ModPagespeedUrlValuedAttribute custom b otherResource
ModPagespeedUrlValuedAttribute custom c hyperlink
</VirtualHost>
nginx:
server {
server_name url_attribute.example.com;
root /path/to/htdocs;
listen 8083;
pagespeed FileCachePath /path/to/pagespeed_cache/;
# Don't actually try to rewrite any resources; the ones in
# rewrite_domains.html don't actually exist.
pagespeed RewriteLevel PassThrough;
# This is used for testing dynamically defined url-valued
# attributes
pagespeed UrlValuedAttribute span src Hyperlink;
pagespeed UrlValuedAttribute hr imgsrc Image;
pagespeed DomainRewriteHyperlinks on;
pagespeed MapRewriteDomain http://dst.example.com http://src.example.com;
pagespeed EnableFilters rewrite_domains;
pagespeed UrlValuedAttribute custom a Image;
pagespeed UrlValuedAttribute custom b otherResource;
pagespeed UrlValuedAttribute custom c hyperlink;
}
class AvoidRenamingIntrospectiveJavascriptTest(psoltest.SystemTest):
"""Test the AvoidRenamingIntrospectiveJavascript feature (ARIS).
ARIS should keep introspective scripts like introspection.js from being
inlined, combined, or otherwise having their urls modified.
"""
def Configure(self):
self.aris_on = self.NewServer(
"aris_on.example.com",
pagespeed="""
AvoidRenamingIntrospectiveJavascript on
InPlaceResourceOptimization on
""")
self.aris_off = self.NewServer(
"aris_off.example.com",
pagespeed="""
AvoidRenamingIntrospectiveJavascript off
InPlaceResourceOptimization on
""")
def TestCombining(self):
url = "avoid_renaming_introspective_javascript.html"
# aris disables js combining for introspective js and only i-js
combine_javascript_url = (
"url" + "?ModPagespeedFilters=combine_javascript")
def OnlyNormalScriptsCombined(response):
return response.body.count("src=") == 2
self.aris_on.FetchUntil(combine_javascript_url,
OnlyNormalScriptsCombined)
# aris disables js combining only when enabled
def AllScriptsCombined(response):
return response.body.count("src=") == 1
self.aris_off.FetchUntil(combine_javascript_url, AllScriptsCombined)
def TestInlining(self):
# aris disables js inlining for introspective js and only i-js
inline_javascript_url = "url" + “?ModPagespeedFilters=inline_javascript”
def IntrospectiveScriptNotInlined(response):
return response.body.count("src=") == 1
self.aris_on.FetchUntil(inline_javascript_url,
IntrospectiveScriptNotInlined)
# aris disables js inlining only when enabled
def AllScriptsInlined(response):
return "src=" not in response.body
self.aris_off.FetchUntil(inline_javascript_url, AllScriptsInlined)
def TestCacheExtensionAndAllCoreFilters(self):
# aris disables js cache extension for i-js and only i-js
rewrite_javascript_url = (
"url" + “?ModPagespeedFilters=rewrite_javascript”)
def NormalScriptsRewritten(response):
return ‘src="../normal.js"’ not in response.body
def IntrospectiveScriptNotRewritten(response):
return ‘src="../introspection.js" in response.body
self.aris_on.FetchUntil(rewrite_javascript_url,
NormalScriptsRewritten,
IntrospectiveScriptNotRewritten)
# aris disables js cache extension only when enabled
def IntrospectiveScriptRewritten(response):
return ‘src="../introspection.js"’ not in response.body
self.aris_off.FetchUntil(rewrite_javascript_url,
NormalScriptsRewritten,
IntrospectiveScriptRewritten)
core_testing_url = "url" + “?ModPagespeedFilters=core,testing”
self.aris_on.FetchUntil(core_testing_url,
NormalScriptsRewritten,
IntrospectiveScriptNotRewritten)
self.aris_off.FetchUntil(core_testing_url,
NormalScriptsRewritten,
IntrospectiveScriptRewritten)
def TestInPlaceRewriting(self):
# rewrite introspective javascript in the in-place flow, even with aris
def CommentRemoved(response):
return "introspective" not in response.body
self.aris_on.FetchUntil(“introspection.js”, CommentRemoved)
This replaces:
debug.conf.template:
ModPagespeedAvoidRenamingIntrospectiveJavascript off
mod_pagespeed_test/avoid_renaming_introspective_javascript_on/.htaccess:
ModPagespeedAvoidRenamingIntrospectiveJavascript on
apache_system_test.sh:
start_test aris disables js combining for introspective js and only i-js
URL="$TEST_ROOT/avoid_renaming_introspective_javascript__on/?\
ModPagespeedFilters=combine_javascript"
FetchUntil $URL 'grep -c src=' 2
start_test aris disables js combining only when enabled
URL="$TEST_ROOT/avoid_renaming_introspective_javascript__off.html?\
ModPagespeedFilters=combine_javascript"
FetchUntil $URL 'grep -c src=' 1
test_filter inline_javascript inlines a small JS file
start_test aris disables js inlining for introspective js and only i-js
URL="$TEST_ROOT/avoid_renaming_introspective_javascript__on/?\
ModPagespeedFilters=inline_javascript"
FetchUntil $URL 'grep -c src=' 1
start_test aris disables js inlining only when enabled
URL="$TEST_ROOT/avoid_renaming_introspective_javascript__off.html?\
ModPagespeedFilters=inline_javascript"
FetchUntil $URL 'grep -c src=' 0
test_filter rewrite_javascript minifies JavaScript and saves bytes.
start_test aris disables js cache extension for i-js and only i-js
URL="$TEST_ROOT/avoid_renaming_introspective_javascript__on/?\
ModPagespeedFilters=rewrite_javascript"
# first check something that should get rewritten to know we're done with
# rewriting
FetchUntil -save $URL 'grep -c "src=\"../normal.js\""' 0
check [ $(grep -c "src=\"../introspection.js\"" $FETCH_FILE) = 1 ]
start_test aris disables js cache extension only when enabled
URL="$TEST_ROOT/avoid_renaming_introspective_javascript__off.html?\
ModPagespeedFilters=rewrite_javascript"
FetchUntil -save $URL 'grep -c src=\"normal.js\"' 0
check [ $(grep -c src=\"introspection.js\" $FETCH_FILE) = 0 ]
# Check that no filter changes urls for introspective javascript if
# avoid_renaming_introspective_javascript is on
start_test aris disables url modification for introspective js
URL="$TEST_ROOT/avoid_renaming_introspective_javascript__on/?\
ModPagespeedFilters=testing,core"
# first check something that should get rewritten to know we're done with
# rewriting
FetchUntil -save $URL 'grep -c src=\"../normal.js\"' 0
check [ $(grep -c src=\"../introspection.js\" $FETCH_FILE) = 1 ]
start_test aris disables url modification only when enabled
URL="$TEST_ROOT/avoid_renaming_introspective_javascript__off.html?\
ModPagespeedFilters=testing,core"
FetchUntil -save $URL 'grep -c src=\"normal.js\"' 0
check [ $(grep -c src=\"introspection.js\" $FETCH_FILE) = 0 ]
And generates the following configurations:
apache:
<VirtualHost localhost:8083>
ServerName aris_on.example.com
DocumentRoot "/path/to/htdocs"
ModPagespeedFileCachePath "/path/to/pagespeed_cache/"
ModPagespeedAvoidRenamingIntrospectiveJavascript on
ModPagespeedInPlaceResourceOptimization on
</VirtualHost>
<VirtualHost localhost:8083>
ServerName aris_off.example.com
DocumentRoot "/path/to/htdocs"
ModPagespeedFileCachePath "/path/to/pagespeed_cache/"
ModPagespeedAvoidRenamingIntrospectiveJavascript off
ModPagespeedInPlaceResourceOptimization on
</VirtualHost>
nginx:
server {
server_name aris_on.example.com;
root /path/to/htdocs;
listen 8083;
pagespeed FileCachePath /path/to/pagespeed_cache/;
pagespeed AvoidRenamingIntrospectiveJavascript on;
pagespeed InPlaceResourceOptimization on;
}
server {
server_name aris_off.example.com;
root /path/to/htdocs;
listen 8083;
pagespeed FileCachePath /path/to/pagespeed_cache/;
pagespeed AvoidRenamingIntrospectiveJavascript off;
pagespeed InPlaceResourceOptimization on;
}
class FuriousTest(psoltest.SystemTest):
"""Test the experiment framework (Furious)."””
def Configure(self):
self.furious_ga = self.NewServer(
"furious.example.com",
pagespeed="""
RunExperiment on
AnalyticsID 123-45-6734
ExperimentVariable 2
ExperimentSpec id=7;enable=recompress_images;disa\
ble=convert_jpeg_to_progressive;percent=50
ExperimentSpec id=2;enable=recompress_images;percent=50
""")
self.furious_no_ga = self.NewServer(
"furious_no_ga.example.com",
pagespeed="""
RunExperiment on
ExperimentVariable 2
ExperimentSpec id=7;enable=recompress_images;disa\
ble=convert_jpeg_to_progressive;percent=50
ExperimentSpec id=2;enable=recompress_images;percent=50
""")
def GaAgnosticFetch(self, *args, **kwargs):
self.furious_ga.Fetch(*args, **kwargs)
self.furiuos_no_ga.Fetch(*args, **kwargs)
def GaAgnosticFetchUntil(self, *args, **kwargs):
self.furious_ga.FetchUntil(*args, **kwargs)
self.furiuos_no_ga.FetchUntil(*args, **kwargs)
def TestSetCookie(self):
# The apache-specific tests that verify that experiments work with
# a .htaccess would go elsewhere.
# Check that we set the _GFURIOUS cookie on cookieless requests.
def CookieIsSet(response):
return response.HasHeader("_GFURIOUS")
self.GaAgnosticFetch("extend_cache.html", CookieIsSet)
# ModPagespeedFilters query param should disable experiments.
def CookieIsNotSet(response):
return not CookieIsSet(response)
self.GaAgnosticFetch("extend_cache.html?ModPagespeed=on&"
"ModPagespeedFilters=rewrite_css", CookieIsNotSet)
# If the user is already assigned, no need to assign them again.
self.GaAgnosticFetch("extend_cache.html"
CookieIsNotSet,
headers=["Cookie: _GFURIOUS=2"])
def TestBeaconIncludesExperimentId(self):
def BeaconIncludesExperimentId(experiment_id):
def helper(response):
return re.match("pagespeed.addInstrumentationInit("
"'/mod_pagespeed_beacon', 'load', ''," '', "
"'%s', '[^']*/extend_cache.html'" % experiment_id,
response.body)
return helper
self.GaAgnosticFetch("extend_cache.html"
BeaconIncludesExperimentId(2),
headers=["Cookie: _GFURIOUS=2"])
self.GaAgnosticFetch("extend_cache.html"
BeaconIncludesExperimentId(7),
headers=["Cookie: _GFURIOUS=7"])
# no-experiment group beacon should not include an experiment id.
self.GaAgnosticFetch("extend_cache.html"
BeaconIncludesExperimentId(“”),
headers=["Cookie: _GFURIOUS=0"])
def TestResourceUrlsIncludeExperimentIndexes(self):
# We expect id=7 to be index=a and id=2 to be index=b because that's the
# order they're defined above.
def ResourceTaggedA(response):
return response.body.count(".pagespeed.a.ic.") == 1
self.GaAgnosticFetch("extend_cache.html", ResourceTaggedA,
headers=["Cookie: _GFURIOUS=7"])
def ResourceTaggedB(response):
return response.body.count(".pagespeed.b.ic.") == 1
self.GaAgnosticFetch("extend_cache.html", ResourceTaggedB,
headers=["Cookie: _GFURIOUS=2"])
def TestImagesDifferWhenUrlSpecifiesDifferentExperiments(self):
# While the images are the same, image B should be smaller because in
# the config file we enable convert_jpeg_to_progressive only for id=2
# (side B). Ideally we would check that it was actually progressive, by
# checking whether "identify -verbose filename" produced "Interlace:
# JPEG" or "Interlace: None", but that would introduce a dependency on
# imagemagick. This is just as accurate, but more brittle (because
# changes to our compression code would change the computed file sizes).
def ByteCount(expected_bytes):
def helper(response):
return len(response.body) == expected_bytes
return helper
self.GaAgnosticFetchUntil(
"/images/xPuzzle.jpg.pagespeed.a.ic.fakehash.jpg", ByteCount(231192))
self.GaAgnosticFetchUntil(
"/images/xPuzzle.jpg.pagespeed.b.ic.fakehash.jpg", ByteCount(216942))
def TestAnalyticsJavascriptAddedOnlyWhenGaIsOn(self)
def AnalyticsJs(response):
return "Experiment:" in response.body
def NoAnalyticsJs(response):
return not AnalyticsJs(response)
# Analytics is not added for any group when GA is off.
self.furious_no_ga.Fetch("extend_cache.html", NoAnalyticsJs,
headers=["Cookie: _GFURIOUS=2"])
self.furious_no_ga.Fetch("extend_cache.html", NoAnalyticsJs,
headers=["Cookie: _GFURIOUS=7"])
self.furious_no_ga.Fetch("extend_cache.html", NoAnalyticsJs,
headers=["Cookie: _GFURIOUS=0"])
# Analytics is added for the experimental group when GA is on.
self.furious_ga.Fetch("extend_cache.html", AnalyticsJs,
headers=["Cookie: _GFURIOUS=2"])
self.furious_ga.Fetch("extend_cache.html", AnalyticsJs,
headers=["Cookie: _GFURIOUS=7"])
# Analytics is not added for the no-experiment group even when GA is on.
self.furious_ga.Fetch("extend_cache.html", NoAnalyticsJs,
headers=["Cookie: _GFURIOUS=0"])
This replaces:
debug.conf.template:
#FURIOUS_GA # This is used for testing the Furious experiment framework.
#FURIOUS_GA ModPagespeedRunExperiment on
#FURIOUS_GA ModPagespeedAnalyticsID "123-45-6734"
#FURIOUS_GA ModPagespeedExperimentVariable 2
#FURIOUS_GA ModPagespeedExperimentSpec "id=7;enable=recompress_images;disa\
ble=convert_jpeg_to_progressive;percent=50"
#FURIOUS_GA ModPagespeedExperimentSpec \
"id=2;enable=recompress_images;percent=50"
#FURIOUS_NO_GA # This is used for testing the Furious experiment framework
#FURIOUS_NO_GA # still works when no analytics ID is specified. It should
#FURIOUS_NO_GA # assign users to experiments and use appropriate
#FURIOUS_NO_GA # experimental options, but not report back to Google
#FURIOUS_NO_GA # Analytics. The instrumentation beacon, however, will still
#FURIOUS_NO_GA # contain the experiment id.
#FURIOUS_NO_GA ModPagespeedRunExperiment on
#FURIOUS_NO_GA ModPagespeedExperimentVariable 2
#FURIOUS_NO_GA ModPagespeedExperimentSpec "id=7;enable=recompress_images;di
sable=convert_jpeg_to_progressive;percent=50"
#FURIOUS_NO_GA ModPagespeedExperimentSpec \
"id=2;enable=recompress_images;percent=50"
apache_furious_test_ga.sh:
start_test Analytics javascript is added for the experimental group.
OUT=$($WGET_DUMP --header='Cookie: _GFURIOUS=2' $EXTEND_CACHE)
check_from "$OUT" fgrep -q 'Experiment: 2'
OUT=$($WGET_DUMP --header='Cookie: _GFURIOUS=7' $EXTEND_CACHE)
check_from "$OUT" fgrep -q 'Experiment: 7'
start_test Analytics javascript is not added for the no-experiment group.
OUT=$($WGET_DUMP --header='Cookie: _GFURIOUS=0' $EXTEND_CACHE)
check_not_from "$OUT" fgrep -q 'Experiment:'
apache_furious_test_no_ga.sh:
start_test Analytics javascript is not added for any group.
OUT=$($WGET_DUMP --header='Cookie: _GFURIOUS=2' $EXTEND_CACHE)
check_not_from "$OUT" fgrep -q 'Experiment:'
OUT=$($WGET_DUMP --header='Cookie: _GFURIOUS=7' $EXTEND_CACHE)
check_not_from "$OUT" fgrep -q 'Experiment:'
OUT=$($WGET_DUMP --header='Cookie: _GFURIOUS=0' $EXTEND_CACHE)
check_not_from "$OUT" fgrep -q 'Experiment:'
apache_furious_test.sh:
echo Testing whether or not Furious is working.
start_test mod_pagespeed_example must have a .htaccess file.
check test -f $EXAMPLE_FILE_DIR/.htaccess
start_test _GFURIOUS cookie is set.
OUT=$($WGET_DUMP $EXTEND_CACHE)
check_from "$OUT" fgrep "_GFURIOUS="
start_test mod_pagespeed_test must not have a .htaccess file.
check_not test -f $TEST_ROOT_FILE_DIR/.htaccess
start_test ModPagespeedFilters query param should disable experiments.
OUT=$($WGET_DUMP '$EXTEND_CACHE?ModPagespeed=on&ModPagespeedFilte\
rs=rewrite_css')
check_not_from "$OUT" fgrep '_GFURIOUS='
start_test If the user is already assigned, no need to assign them again.
OUT=$($WGET_DUMP --header='Cookie: _GFURIOUS=2' $EXTEND_CACHE)
check_not_from "$OUT" fgrep '_GFURIOUS='
start_test The beacon should include the experiment id.
OUT=$($WGET_DUMP --header='Cookie: _GFURIOUS=2' $EXTEND_CACHE)
check_from "$OUT" grep "pagespeed.addInstrumentationInit('/mod_pagespeed_be\
acon', 'load', '', '', '2', 'http://localhost\
[:0-9]*/mod_pagespeed_example/extend_cache.html');"
OUT=$($WGET_DUMP --header='Cookie: _GFURIOUS=7' $EXTEND_CACHE)
check_from "$OUT" grep "pagespeed.addInstrumentationInit('/mod_pagespeed_be\
acon', 'load', '', '', '7', 'http://localhost\
[:0-9]*/mod_pagespeed_example/extend_cache.html');"
start_test no-experiment group beacon should not include an experiment id.
OUT=$($WGET_DUMP --header='Cookie: _GFURIOUS=0' $EXTEND_CACHE)
check_not_from "$OUT" grep 'mod_pagespeed_beacon.*exptid'
# We expect id=7 to be index=a and id=2 to be index=b because that's the
# order they're defined in the config file.
start_test Resource urls are rewritten to include experiment indexes.
WGET_ARGS="--header 'Cookie:_GFURIOUS=7'" FetchUntil $EXTEND_CACHE \
"fgrep -c .pagespeed.a.ic." 1
WGET_ARGS="--header 'Cookie:_GFURIOUS=2'" FetchUntil $EXTEND_CACHE \
"fgrep -c .pagespeed.b.ic." 1
OUT=$($WGET_DUMP --header='Cookie: _GFURIOUS=7' $EXTEND_CACHE)
check_from "$OUT" fgrep ".pagespeed.a.ic."
OUT=$($WGET_DUMP --header='Cookie: _GFURIOUS=2' $EXTEND_CACHE)
check_from "$OUT" fgrep ".pagespeed.b.ic."
start_test Images are different when url specifies different experiments.
# While the images are the same, image B should be smaller because in the
# config file we enable convert_jpeg_to_progressive only for id=2 (side B).
# Ideally we would check that it was actually progressive, by checking
# whether "identify -verbose filename" produced "Interlace: JPEG" or
# "Interlace: None", but that would introduce a dependency on imagemagick.
# This is just as accurate, but more brittle (because changes to our
# compression code would change the computed file sizes).
IMG_A="$EXAMPLE/images/xPuzzle.jpg.pagespeed.a.ic.fakehash.jpg"
IMG_B="$EXAMPLE/images/xPuzzle.jpg.pagespeed.b.ic.fakehash.jpg"
FetchUntil $IMG_A 'wc -c' 231192
FetchUntil $IMG_B 'wc -c' 216942
And generates the following configurations:
apache:
<VirtualHost localhost:8083>
ServerName furious_ga.example.com
DocumentRoot "/path/to/htdocs"
ModPagespeedFileCachePath "/path/to/pagespeed_cache/"
ModPagespeedRunExperiment on
ModPagespeedAnalyticsID "123-45-6734"
ModPagespeedExperimentVariable 2
ModPagespeedExperimentSpec "id=7;enable=recompress_images;disable=conv\
ert_jpeg_to_progressive;percent=50"
ModPagespeedExperimentSpec "id=2;enable=recompress_images;percent=50"
</VirtualHost>
<VirtualHost localhost:8083>
ServerName furious_no_ga.example.com
DocumentRoot "/path/to/htdocs"
ModPagespeedFileCachePath "/path/to/pagespeed_cache/"
ModPagespeedRunExperiment on
ModPagespeedExperimentVariable 2
ModPagespeedExperimentSpec "id=7;enable=recompress_images;disable=conv\
ert_jpeg_to_progressive;percent=50"
ModPagespeedExperimentSpec "id=2;enable=recompress_images;percent=50"
</VirtualHost>
nginx:
server {
server_name furious_ga.example.com;
root /path/to/htdocs;
listen 8083;
pagespeed FileCachePath /path/to/pagespeed_cache/;
pagespeed RunExperiment on;
pagespeed AnalyticsID "123-45-6734";
pagespeed ExperimentVariable 2;
pagespeed ExperimentSpec "id=7;enable=recompress_images;disable=conv\
ert_jpeg_to_progressive;percent=50";
pagespeed ExperimentSpec "id=2;enable=recompress_images;percent=50";
}
server {
server_name furious_no_ga.example.com;
root /path/to/htdocs;
listen 8083;
pagespeed FileCachePath /path/to/pagespeed_cache/;
pagespeed RunExperiment on;
pagespeed ExperimentVariable 2;
pagespeed ExperimentSpec "id=7;enable=recompress_images;disable=conv\
ert_jpeg_to_progressive;percent=50";
pagespeed ExperimentSpec "id=2;enable=recompress_images;percent=50";
}
Test classes (AvoidRenamingIntrospectiveJavascriptTest, UrlValuedAttributeTest, …) all get their Configure() methods called serially when we start up testing. Then the test runner stands up a server supporting all relevant configurations (or multiple servers). Then we can run all Test*() methods on all the tests, and this stage can be as parallel as we like.