#!/bin/bash # Copyright 2015 The Bazel Authors. All rights reserved. # # 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. # Unit tests for docker_build global DIR := $[cd $[dirname $(BASH_SOURCE[0])] && pwd] source $(DIR)/testenv.sh || do { echo "testenv.sh not found!" > !2; exit 1setconst global FOO = "bar"; } readonly PLATFORM = $[uname -s | tr 'A-Z' 'a-z] if test $(PLATFORM) = "darwin" {setconst global FOO = "bar" readonly MAGIC_TIMESTAMP = $[date -r 0 "+%b %e %Y] } else {setconst global FOO = "bar" readonly MAGIC_TIMESTAMP = $[date --date=@0 "+%F %R] } proc EXPECT_CONTAINS { var complete = $(1) var substring = $(2) var message = $(3:-Expected '${substring}' not found in '${complete}') echo $(complete) | grep -Fsq -- $(substring) \ || fail $message } proc check_property { var property = $(1) var tarball = $(2) var layer = $(3) var expected = $(4) var test_data = ""$(TEST_DATA_DIR)/$(tarball).tar"" var metadata = $[tar xOf $(test_data) "./$(layer)/json] # This would be much more accurate if we had 'jq' everywhere. EXPECT_CONTAINS $(metadata) "\"$(property)\": $(expected)" } proc check_no_property { var property = $(1) var tarball = $(2) var layer = $(3) var test_data = ""$(TEST_DATA_DIR)/$(tarball).tar"" tar xOf $(test_data) "./$(layer)/json" >$TEST_log expect_not_log "\"$(property)\":" # notop variant test_data := ""$(TEST_DATA_DIR)/notop_$(tarball).tar"" tar xOf $(test_data) "./$(layer)/json" >$TEST_log expect_not_log "\"$(property)\":" } proc check_size { check_property Size $(@) } proc check_id { check_property id $(@) } proc check_parent { check_property parent $(@) } proc check_entrypoint { global input := $1 shift check_property Entrypoint $(input) $(@) check_property Entrypoint "notop_$(input)" $(@) } proc check_cmd { global input := $1 shift check_property Cmd $(input) $(@) check_property Cmd "notop_$(input)" $(@) } proc check_ports { global input := $1 shift check_property ExposedPorts $(input) $(@) check_property ExposedPorts $(input) $(@) } proc check_volumes { global input := $1 shift check_property Volumes $(input) $(@) check_property Volumes "notop_$(input)" $(@) } proc check_env { global input := $1 shift check_property Env $(input) $(@) check_property Env "notop_$(input)" $(@) } proc check_label { global input := $1 shift check_property Label $(input) $(@) check_property Label "notop_$(input)" $(@) } proc check_workdir { global input := $1 shift check_property WorkingDir $(input) $(@) check_property WorkingDir "notop_$(input)" $(@) } proc check_user { global input := $1 shift check_property User $(input) $(@) check_property User "notop_$(input)" $(@) } proc check_layers_aux { var input = $(1) shift 1 var expected_layers = '('${*}) var expected_layers_sorted = '( '$(for i in ${expected_layers[*]}; do echo $i; done | sort) ) var test_data = ""$(TEST_DATA_DIR)/$(input).tar"" # Verbose output for testing. tar tvf $(test_data) var actual_layers = '( '$(tar tvf ${test_data} | tr -s ' ' | cut -d' ' -f 4- | sort \ | cut -d'/' -f 2 | grep -E '^[0-9a-f]+$' | sort | uniq)) # Verbose output for testing. echo Expected: $(expected_layers_sorted[@]) echo Actual: $(actual_layers[@]) check_eq $(#expected_layers[@]) $(#actual_layers[@]) var index = '0' var parent = '' while [ "${index}" -lt "${#expected_layers[@]}" ] { # Check that the nth sorted layer matches check_eq $(expected_layers_sorted[$index]) $(actual_layers[$index]) # Grab the ordered layer and check it. var layer = $(expected_layers[$index]) # Verbose output for testing. echo Checking layer: $(layer) var listing = $[tar xOf $(test_data) "./$(layer)/layer.tar" | tar tv] # Check that all files in the layer, if any, have the magic timestamp check_eq $[echo $(listing) | grep -Fv $(MAGIC_TIMESTAMP) || true] "" check_id $(input) $(layer) "\"$(layer)\"" # Check that the layer contains its predecessor as its parent in the JSON. if [[ -n "${parent}" ]] { check_parent $(input) $(layer) "\"$(parent)\"" } # Check that the layer's size metadata matches the layer's tarball's size. var layer_size = $[tar xOf $(test_data) "./$(layer)/layer.tar" | wc -c | xargs] check_size $(input) $(layer) $(layer_size) index := $(index + 1) parent := $layer } } proc check_layers { var input = $1 shift check_layers_aux $input @Argv check_layers_aux "notop_$input" @Argv } proc test_gen_image { grep -Fsq "./gen.out" "$TEST_DATA_DIR/gen_image.tar" \ || fail "'./gen.out' not found in '$TEST_DATA_DIR/gen_image.tar'" } proc test_dummy_repository { var layer = '"0279f3ce8b08d10506abcf452393b3e48439f5eca41b836fae59a0d509fbafea'" var test_data = ""$(TEST_DATA_DIR)/dummy_repository.tar"" check_layers_aux "dummy_repository" $layer var repositories = $[tar xOf $(test_data) "./repositories] # This would really need to use `jq` instead. echo $(repositories) | \ grep -Esq -- "\"gcr.io/dummy/[a-zA-Z_]*_docker_testdata\": {" \ || fail "Cannot find image in repository gcr.io/dummy in '$(repositories)'" EXPECT_CONTAINS $(repositories) "\"dummy_repository\": \"$layer\"" } proc test_files_base { check_layers "files_base" \ "82ca3945f7d07df82f274d7fafe83fd664c2154e5c64c988916ccd5b217bb710" } proc test_files_with_files_base { check_layers "files_with_files_base" \ "82ca3945f7d07df82f274d7fafe83fd664c2154e5c64c988916ccd5b217bb710" \ "84c0d09919ae8b06cb6b064d8cd5eab63341a46f11ccc7ecbe270ad3e1f52744" } proc test_tar_base { check_layers "tar_base" \ "8b9e4db9dd4b990ee6d8adc2843ad64702ad9063ae6c22e8ca5f94aa54e71277" # Check that this layer doesn't have any entrypoint data by looking # for *any* entrypoint. check_no_property "Entrypoint" "tar_base" \ "8b9e4db9dd4b990ee6d8adc2843ad64702ad9063ae6c22e8ca5f94aa54e71277" } proc test_tar_with_tar_base { check_layers "tar_with_tar_base" \ "8b9e4db9dd4b990ee6d8adc2843ad64702ad9063ae6c22e8ca5f94aa54e71277" \ "1cc81a2aaec2e3727d98d48bf9ba09d3ac96ef48adf5edae861d15dd0191dc40" } proc test_directory_with_tar_base { check_layers "directory_with_tar_base" \ "8b9e4db9dd4b990ee6d8adc2843ad64702ad9063ae6c22e8ca5f94aa54e71277" \ "e56ddeb8279698484f50d480f71cb5380223ad0f451766b7b9a9348129d02542" } proc test_files_with_tar_base { check_layers "files_with_tar_base" \ "8b9e4db9dd4b990ee6d8adc2843ad64702ad9063ae6c22e8ca5f94aa54e71277" \ "f099727fa58f9b688e77b511b3cc728b86ae0e84d197b9330bd51082ad5589f2" } proc test_workdir_with_tar_base { check_layers "workdir_with_tar_base" \ "8b9e4db9dd4b990ee6d8adc2843ad64702ad9063ae6c22e8ca5f94aa54e71277" \ "f24cbe53bd1b78909c6dba0bd47016354f3488b35b85aeee68ecc423062b927e" } proc test_tar_with_files_base { check_layers "tar_with_files_base" \ "82ca3945f7d07df82f274d7fafe83fd664c2154e5c64c988916ccd5b217bb710" \ "bee1a325e4b51a1dcfd7e447987b4e130590815865ab22e8744878053d525f20" } proc test_base_with_entrypoint { check_layers "base_with_entrypoint" \ "4acbeb0495918726c0107e372b421e1d2a6fd4825d58fc3f0b0b2a719fb3ce1b" check_entrypoint "base_with_entrypoint" \ "4acbeb0495918726c0107e372b421e1d2a6fd4825d58fc3f0b0b2a719fb3ce1b" \ '["/bar"]' # Check that the base layer has a port exposed. check_ports "base_with_entrypoint" \ "4acbeb0495918726c0107e372b421e1d2a6fd4825d58fc3f0b0b2a719fb3ce1b" \ '{"8080/tcp": {}}' } proc test_derivative_with_shadowed_cmd { check_layers "derivative_with_shadowed_cmd" \ "4acbeb0495918726c0107e372b421e1d2a6fd4825d58fc3f0b0b2a719fb3ce1b" \ "e35f57dc6c1e84ae67dcaaf3479a3a3c0f52ac4d194073bd6214e04c05beab42" } proc test_derivative_with_cmd { check_layers "derivative_with_cmd" \ "4acbeb0495918726c0107e372b421e1d2a6fd4825d58fc3f0b0b2a719fb3ce1b" \ "e35f57dc6c1e84ae67dcaaf3479a3a3c0f52ac4d194073bd6214e04c05beab42" \ "186289545131e34510006ac79498078dcf41736a5eb9a36920a6b30d3f45bc01" check_entrypoint "derivative_with_cmd" \ "186289545131e34510006ac79498078dcf41736a5eb9a36920a6b30d3f45bc01" \ '["/bar"]' # Check that the middle layer has our shadowed arg. check_cmd "derivative_with_cmd" \ "e35f57dc6c1e84ae67dcaaf3479a3a3c0f52ac4d194073bd6214e04c05beab42" \ '["shadowed-arg"]' # Check that our topmost layer excludes the shadowed arg. check_cmd "derivative_with_cmd" \ "186289545131e34510006ac79498078dcf41736a5eb9a36920a6b30d3f45bc01" \ '["arg1", "arg2"]' # Check that the topmost layer has the ports exposed by the bottom # layer, and itself. check_ports "derivative_with_cmd" \ "186289545131e34510006ac79498078dcf41736a5eb9a36920a6b30d3f45bc01" \ '{"80/tcp": {}, "8080/tcp": {}}' } proc test_derivative_with_volume { check_layers "derivative_with_volume" \ "125e7cfb9d4a6d803a57b88bcdb05d9a6a47ac0d6312a8b4cff52a2685c5c858" \ "08424283ad3a7e020e210bec22b166d7ebba57f7ba2d0713c2fd7bd1e2038f88" # Check that the topmost layer has the ports exposed by the bottom # layer, and itself. check_volumes "derivative_with_volume" \ "125e7cfb9d4a6d803a57b88bcdb05d9a6a47ac0d6312a8b4cff52a2685c5c858" \ '{"/logs": {}}' check_volumes "derivative_with_volume" \ "08424283ad3a7e020e210bec22b166d7ebba57f7ba2d0713c2fd7bd1e2038f88" \ '{"/asdf": {}, "/blah": {}, "/logs": {}}' } proc test_generated_tarball { check_layers "generated_tarball" \ "54b8328604115255cc76c12a2a51939be65c40bf182ff5a898a5fb57c38f7772" } proc test_with_env { check_layers "with_env" \ "125e7cfb9d4a6d803a57b88bcdb05d9a6a47ac0d6312a8b4cff52a2685c5c858" \ "42a1bd0f449f61a23b8a7776875ffb6707b34ee99c87d6428a7394f5e55e8624" check_env "with_env" \ "42a1bd0f449f61a23b8a7776875ffb6707b34ee99c87d6428a7394f5e55e8624" \ '["bar=blah blah blah", "foo=/asdf"]' } proc test_with_double_env { check_layers "with_double_env" \ "125e7cfb9d4a6d803a57b88bcdb05d9a6a47ac0d6312a8b4cff52a2685c5c858" \ "42a1bd0f449f61a23b8a7776875ffb6707b34ee99c87d6428a7394f5e55e8624" \ "576a9fd9c690be04dc7aacbb9dbd1f14816e32dbbcc510f4d42325bbff7163dd" # Check both the aggregation and the expansion of embedded variables. check_env "with_double_env" \ "576a9fd9c690be04dc7aacbb9dbd1f14816e32dbbcc510f4d42325bbff7163dd" \ '["bar=blah blah blah", "baz=/asdf blah blah blah", "foo=/asdf"]' } proc test_with_label { check_layers "with_label" \ "125e7cfb9d4a6d803a57b88bcdb05d9a6a47ac0d6312a8b4cff52a2685c5c858" \ "eba6abda3d259ab6ed5f4d48b76df72a5193fad894d4ae78fbf0a363d8f9e8fd" check_label "with_label" \ "eba6abda3d259ab6ed5f4d48b76df72a5193fad894d4ae78fbf0a363d8f9e8fd" \ '["com.example.bar={\"name\": \"blah\"}", "com.example.baz=qux", "com.example.foo={\"name\": \"blah\"}"]' } proc test_with_double_label { check_layers "with_double_label" \ "125e7cfb9d4a6d803a57b88bcdb05d9a6a47ac0d6312a8b4cff52a2685c5c858" \ "eba6abda3d259ab6ed5f4d48b76df72a5193fad894d4ae78fbf0a363d8f9e8fd" \ "bfe88fbb5e24fc5bff138f7a1923d53a2ee1bbc8e54b6f5d9c371d5f48b6b023" \ check_label "with_double_label" \ "bfe88fbb5e24fc5bff138f7a1923d53a2ee1bbc8e54b6f5d9c371d5f48b6b023" \ '["com.example.bar={\"name\": \"blah\"}", "com.example.baz=qux", "com.example.foo={\"name\": \"blah\"}", "com.example.qux={\"name\": \"blah-blah\"}"]' } proc test_with_user { check_user "with_user" \ "65664d4d78ff321684e2a8bf165792ce562c5990c9ba992e6288dcb1ec7f675c" \ "\"nobody\"" } proc get_layer_listing { var input = $1 var layer = $2 var test_data = ""$(TEST_DATA_DIR)/$(input).tar"" tar xOf $(test_data) \ "./$(layer)/layer.tar" | tar tv | sed -e 's/^.*:00 //' } proc test_data_path { var no_data_path_sha = '"451d182e5c71840f00ba9726dc0239db73a21b7e89e79c77f677e3f7c5c23d44'" var data_path_sha = '"9a41c9e1709558f7ef06f28f66e9056feafa7e0f83990801e1b27c987278d8e8'" var absolute_data_path_sha = '"f196c42ab4f3eb850d9655b950b824db2c99c01527703ac486a7b48bb2a34f44'" var root_data_path_sha = '"19d7fd26d67bfaeedd6232dcd441f14ee163bc81c56ed565cc20e73311c418b6'" check_layers_aux "no_data_path_image" $(no_data_path_sha) check_layers_aux "data_path_image" $(data_path_sha) check_layers_aux "absolute_data_path_image" $(absolute_data_path_sha) check_layers_aux "root_data_path_image" $(root_data_path_sha) # Without data_path = "." the file will be inserted as `./test` # (since it is the path in the package) and with data_path = "." # the file will be inserted relatively to the testdata package # (so `./test/test`). check_eq $[get_layer_listing "no_data_path_image" $(no_data_path_sha)] \ './ ./test' check_eq $[get_layer_listing "data_path_image" $(data_path_sha)] \ './ ./test/ ./test/test' # With an absolute path for data_path, we should strip that prefix # from the files' paths. Since the testdata images are in # //tools/build_defs/docker/testdata and data_path is set to # "/tools/build_defs", we should have `docker` as the top-level # directory. check_eq $[get_layer_listing "absolute_data_path_image" $(absolute_data_path_sha)] \ './ ./docker/ ./docker/testdata/ ./docker/testdata/test/ ./docker/testdata/test/test' # With data_path = "/", we expect the entire path from the repository # root. check_eq $[get_layer_listing "root_data_path_image" $(root_data_path_sha)] \ "./ ./tools/ ./tools/build_defs/ ./tools/build_defs/docker/ ./tools/build_defs/docker/testdata/ ./tools/build_defs/docker/testdata/test/ ./tools/build_defs/docker/testdata/test/test" } proc test_extras_with_deb { var test_data = ""$(TEST_DATA_DIR)/extras_with_deb.tar"" var sha = $[tar xOf $(test_data) ./top] # The content of the layer should have no duplicate var layer_listing = $[get_layer_listing "extras_with_deb" $(sha) | sort] check_eq $(layer_listing) \ "./ ./etc/ ./etc/nsswitch.conf ./tmp/ ./usr/ ./usr/bin/ ./usr/bin/java -> /path/to/bin/java ./usr/titi" } run_suite "build_test" (CommandList children: [ (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:DIR) op: Equal rhs: { (CommandSubPart command_list: (CommandList children: [ (AndOr children: [ (C {(cd)} { (DQ (CommandSubPart command_list: (CommandList children: [ (C {(dirname)} { (DQ (BracedVarSub token: bracket_op: (ArrayIndex expr: (ArithWord w:{(Lit_Digits 0)}) ) spids: [57 62] ) ) } ) ] ) left_token: spids: [53 64] ) ) } ) (C {(pwd)}) ] op_id: Op_DAmp ) ] ) left_token: spids: [49 70] ) } spids: [48] ) ] spids: [48] ) (AndOr children: [ (C {(source)} {(${ VSub_Name DIR) (/testenv.sh)}) (BraceGroup children: [ (Sentence child: (SimpleCommand words: [{(echo)} {(DQ ("testenv.sh not found!"))}] redirects: [(Redir op_id:Redir_GreatAnd fd:-1 arg_word:{(2)} spids:[89])] ) terminator: ) (Sentence child:(C {(exit)} {(1)}) terminator:) ] spids: [81] ) ] op_id: Op_DPipe ) (Assignment keyword: Assign_Readonly pairs: [ (assign_pair lhs: (LhsName name:PLATFORM) op: Equal rhs: { (DQ (CommandSubPart command_list: (CommandList children: [ (Pipeline children: [(C {(uname)} {(-s)}) (C {(tr)} {(SQ )} {(SQ )})] negated: False ) ] ) left_token: spids: [105 121] ) ) } spids: [103] ) ] spids: [101] ) (If arms: [ (if_arm cond: [ (Sentence child: (C {(Lit_Other "[")} {(DQ (${ VSub_Name PLATFORM))} {(Lit_Other "=")} {(DQ (darwin))} {(Lit_Other "]")} ) terminator: ) ] action: [ (Assignment keyword: Assign_Readonly pairs: [ (assign_pair lhs: (LhsName name:MAGIC_TIMESTAMP) op: Equal rhs: { (DQ (CommandSubPart command_list: (CommandList children: [(C {(date)} {(-r)} {(0)} {(DQ ("+%b %e %Y"))})] ) left_token: spids: [150 160] ) ) } spids: [148] ) ] spids: [146] ) ] spids: [-1 143] ) ] else_action: [ (Assignment keyword: Assign_Readonly pairs: [ (assign_pair lhs: (LhsName name:MAGIC_TIMESTAMP) op: Equal rhs: { (DQ (CommandSubPart command_list: (CommandList children: [ (C {(date)} {(--date) (Lit_Other "=") (Lit_Other "@") (0)} {(DQ ("+%F %R"))}) ] ) left_token: spids: [170 181] ) ) } spids: [168] ) ] spids: [166] ) ] spids: [163 184] ) (FuncDef name: EXPECT_CONTAINS body: (BraceGroup children: [ (Assignment keyword: Assign_Local pairs: [ (assign_pair lhs: (LhsName name:complete) op: Equal rhs: {(DQ (${ VSub_Number 1))} spids: [198] ) ] spids: [196] ) (Assignment keyword: Assign_Local pairs: [ (assign_pair lhs: (LhsName name:substring) op: Equal rhs: {(DQ (${ VSub_Number 2))} spids: [208] ) ] spids: [206] ) (Assignment keyword: Assign_Local pairs: [ (assign_pair lhs: (LhsName name:message) op: Equal rhs: { (DQ (BracedVarSub token: suffix_op: (StringUnary op_id: VTest_ColonHyphen arg_word: {("Expected '") (${ VSub_Name substring) ("' not found in '") (${ VSub_Name complete) ("'") } ) spids: [220 232] ) ) } spids: [218] ) ] spids: [216] ) (AndOr children: [ (Pipeline children: [ (C {(echo)} {(DQ (${ VSub_Name complete))}) (C {(grep)} {(-Fsq)} {(--)} {(DQ (${ VSub_Name substring))}) ] negated: False ) (C {(fail)} {(DQ ($ VSub_Name "$message"))}) ] op_id: Op_DPipe ) ] spids: [193] ) spids: [187 192] ) (FuncDef name: check_property body: (BraceGroup children: [ (Assignment keyword: Assign_Local pairs: [ (assign_pair lhs: (LhsName name:property) op: Equal rhs: {(DQ (${ VSub_Number 1))} spids: [283] ) ] spids: [281] ) (Assignment keyword: Assign_Local pairs: [ (assign_pair lhs: (LhsName name:tarball) op: Equal rhs: {(DQ (${ VSub_Number 2))} spids: [293] ) ] spids: [291] ) (Assignment keyword: Assign_Local pairs: [ (assign_pair lhs: (LhsName name:layer) op: Equal rhs: {(DQ (${ VSub_Number 3))} spids: [303] ) ] spids: [301] ) (Assignment keyword: Assign_Local pairs: [ (assign_pair lhs: (LhsName name:expected) op: Equal rhs: {(DQ (${ VSub_Number 4))} spids: [313] ) ] spids: [311] ) (Assignment keyword: Assign_Local pairs: [ (assign_pair lhs: (LhsName name:test_data) op: Equal rhs: {(DQ (${ VSub_Name TEST_DATA_DIR) (/) (${ VSub_Name tarball) (.tar))} spids: [323] ) ] spids: [321] ) (Assignment keyword: Assign_Local pairs: [ (assign_pair lhs: (LhsName name:metadata) op: Equal rhs: { (DQ (CommandSubPart command_list: (CommandList children: [ (C {(tar)} {(xOf)} {(DQ (${ VSub_Name test_data))} {(DQ (./) (${ VSub_Name layer) (/json))} ) ] ) left_token: spids: [341 359] ) ) } spids: [339] ) ] spids: [337] ) (C {(EXPECT_CONTAINS)} {(DQ (${ VSub_Name metadata))} { (DQ (EscapedLiteralPart token:) (${ VSub_Name property) (EscapedLiteralPart token:) (": ") (${ VSub_Name expected) ) } ) ] spids: [278] ) spids: [272 277] ) (FuncDef name: check_no_property body: (BraceGroup children: [ (Assignment keyword: Assign_Local pairs: [ (assign_pair lhs: (LhsName name:property) op: Equal rhs: {(DQ (${ VSub_Number 1))} spids: [402] ) ] spids: [400] ) (Assignment keyword: Assign_Local pairs: [ (assign_pair lhs: (LhsName name:tarball) op: Equal rhs: {(DQ (${ VSub_Number 2))} spids: [412] ) ] spids: [410] ) (Assignment keyword: Assign_Local pairs: [ (assign_pair lhs: (LhsName name:layer) op: Equal rhs: {(DQ (${ VSub_Number 3))} spids: [422] ) ] spids: [420] ) (Assignment keyword: Assign_Local pairs: [ (assign_pair lhs: (LhsName name:test_data) op: Equal rhs: {(DQ (${ VSub_Name TEST_DATA_DIR) (/) (${ VSub_Name tarball) (.tar))} spids: [432] ) ] spids: [430] ) (SimpleCommand words: [ {(tar)} {(xOf)} {(DQ (${ VSub_Name test_data))} {(DQ (./) (${ VSub_Name layer) (/json))} ] redirects: [ (Redir op_id: Redir_Great fd: -1 arg_word: {($ VSub_Name "$TEST_log")} spids: [464] ) ] ) (C {(expect_not_log)} { (DQ (EscapedLiteralPart token:) (${ VSub_Name property) (EscapedLiteralPart token:) (":") ) } ) (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:test_data) op: Equal rhs: {(DQ (${ VSub_Name TEST_DATA_DIR) (/notop_) (${ VSub_Name tarball) (.tar))} spids: [485] ) ] spids: [485] ) (SimpleCommand words: [ {(tar)} {(xOf)} {(DQ (${ VSub_Name test_data))} {(DQ (./) (${ VSub_Name layer) (/json))} ] redirects: [ (Redir op_id: Redir_Great fd: -1 arg_word: {($ VSub_Name "$TEST_log")} spids: [516] ) ] ) (C {(expect_not_log)} { (DQ (EscapedLiteralPart token:) (${ VSub_Name property) (EscapedLiteralPart token:) (":") ) } ) ] spids: [397] ) spids: [391 396] ) (FuncDef name: check_size body: (BraceGroup children: [(C {(check_property)} {(Size)} {(DQ (${ VSub_At "@"))})] spids: [540] ) spids: [534 539] ) (FuncDef name: check_id body: (BraceGroup children:[(C {(check_property)} {(id)} {(DQ (${ VSub_At "@"))})] spids:[562]) spids: [556 561] ) (FuncDef name: check_parent body: (BraceGroup children: [(C {(check_property)} {(parent)} {(DQ (${ VSub_At "@"))})] spids: [584] ) spids: [578 583] ) (FuncDef name: check_entrypoint body: (BraceGroup children: [ (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:input) op: Equal rhs: {(DQ ($ VSub_Number "$1"))} spids: [609] ) ] spids: [609] ) (C {(shift)}) (C {(check_property)} {(Entrypoint)} {(DQ (${ VSub_Name input))} {(DQ (${ VSub_At "@"))}) (C {(check_property)} {(Entrypoint)} {(DQ (notop_) (${ VSub_Name input))} {(DQ (${ VSub_At "@"))} ) ] spids: [606] ) spids: [600 605] ) (FuncDef name: check_cmd body: (BraceGroup children: [ (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:input) op: Equal rhs: {(DQ ($ VSub_Number "$1"))} spids: [664] ) ] spids: [664] ) (C {(shift)}) (C {(check_property)} {(Cmd)} {(DQ (${ VSub_Name input))} {(DQ (${ VSub_At "@"))}) (C {(check_property)} {(Cmd)} {(DQ (notop_) (${ VSub_Name input))} {(DQ (${ VSub_At "@"))}) ] spids: [661] ) spids: [655 660] ) (FuncDef name: check_ports body: (BraceGroup children: [ (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:input) op: Equal rhs: {(DQ ($ VSub_Number "$1"))} spids: [719] ) ] spids: [719] ) (C {(shift)}) (C {(check_property)} {(ExposedPorts)} {(DQ (${ VSub_Name input))} {(DQ (${ VSub_At "@"))}) (C {(check_property)} {(ExposedPorts)} {(DQ (${ VSub_Name input))} {(DQ (${ VSub_At "@"))}) ] spids: [716] ) spids: [710 715] ) (FuncDef name: check_volumes body: (BraceGroup children: [ (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:input) op: Equal rhs: {(DQ ($ VSub_Number "$1"))} spids: [773] ) ] spids: [773] ) (C {(shift)}) (C {(check_property)} {(Volumes)} {(DQ (${ VSub_Name input))} {(DQ (${ VSub_At "@"))}) (C {(check_property)} {(Volumes)} {(DQ (notop_) (${ VSub_Name input))} {(DQ (${ VSub_At "@"))}) ] spids: [770] ) spids: [764 769] ) (FuncDef name: check_env body: (BraceGroup children: [ (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:input) op: Equal rhs: {(DQ ($ VSub_Number "$1"))} spids: [828] ) ] spids: [828] ) (C {(shift)}) (C {(check_property)} {(Env)} {(DQ (${ VSub_Name input))} {(DQ (${ VSub_At "@"))}) (C {(check_property)} {(Env)} {(DQ (notop_) (${ VSub_Name input))} {(DQ (${ VSub_At "@"))}) ] spids: [825] ) spids: [819 824] ) (FuncDef name: check_label body: (BraceGroup children: [ (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:input) op: Equal rhs: {(DQ ($ VSub_Number "$1"))} spids: [883] ) ] spids: [883] ) (C {(shift)}) (C {(check_property)} {(Label)} {(DQ (${ VSub_Name input))} {(DQ (${ VSub_At "@"))}) (C {(check_property)} {(Label)} {(DQ (notop_) (${ VSub_Name input))} {(DQ (${ VSub_At "@"))}) ] spids: [880] ) spids: [874 879] ) (FuncDef name: check_workdir body: (BraceGroup children: [ (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:input) op: Equal rhs: {(DQ ($ VSub_Number "$1"))} spids: [938] ) ] spids: [938] ) (C {(shift)}) (C {(check_property)} {(WorkingDir)} {(DQ (${ VSub_Name input))} {(DQ (${ VSub_At "@"))}) (C {(check_property)} {(WorkingDir)} {(DQ (notop_) (${ VSub_Name input))} {(DQ (${ VSub_At "@"))} ) ] spids: [935] ) spids: [929 934] ) (FuncDef name: check_user body: (BraceGroup children: [ (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:input) op: Equal rhs: {(DQ ($ VSub_Number "$1"))} spids: [993] ) ] spids: [993] ) (C {(shift)}) (C {(check_property)} {(User)} {(DQ (${ VSub_Name input))} {(DQ (${ VSub_At "@"))}) (C {(check_property)} {(User)} {(DQ (notop_) (${ VSub_Name input))} {(DQ (${ VSub_At "@"))}) ] spids: [990] ) spids: [984 989] ) (FuncDef name: check_layers_aux body: (BraceGroup children: [ (Assignment keyword: Assign_Local pairs: [ (assign_pair lhs: (LhsName name:input) op: Equal rhs: {(${ VSub_Number 1)} spids: [1050] ) ] spids: [1048] ) (C {(shift)} {(1)}) (Assignment keyword: Assign_Local pairs: [ (assign_pair lhs: (LhsName name:expected_layers) op: Equal rhs: {(ArrayLiteralPart words:[{(${ VSub_Star "*")}])} spids: [1063] ) ] spids: [1061] ) (Assignment keyword: Assign_Local pairs: [ (assign_pair lhs: (LhsName name:expected_layers_sorted) op: Equal rhs: { (ArrayLiteralPart words: [ { (CommandSubPart command_list: (CommandList children: [ (Pipeline children: [ (ForEach iter_name: i iter_words: [ { (BracedVarSub token: bracket_op: (WholeArray op_id:Arith_Star) spids: [1085 1090] ) } ] do_arg_iter: False body: (DoGroup children: [ (Sentence child: (C {(echo)} {($ VSub_Name "$i")}) terminator: ) ] spids: [1093 1100] ) spids: [1084 1091] ) (C {(sort)}) ] negated: False ) ] ) left_token: spids: [1078 1105] ) } ] ) } spids: [1074] ) ] spids: [1072] ) (Assignment keyword: Assign_Local pairs: [ (assign_pair lhs: (LhsName name:test_data) op: Equal rhs: {(DQ (${ VSub_Name TEST_DATA_DIR) (/) (${ VSub_Name input) (.tar))} spids: [1113] ) ] spids: [1111] ) (C {(tar)} {(tvf)} {(DQ (${ VSub_Name test_data))}) (Assignment keyword: Assign_Local pairs: [ (assign_pair lhs: (LhsName name:actual_layers) op: Equal rhs: { (ArrayLiteralPart words: [ { (CommandSubPart command_list: (CommandList children: [ (Pipeline children: [ (C {(tar)} {(tvf)} {(${ VSub_Name test_data)}) (C {(tr)} {(-s)} {(SQ <" ">)}) (C {(cut)} {(-d) (SQ <" ">)} {(-f)} {(4-)}) (C {(sort)}) (C {(cut)} {(-d) (SQ )} {(-f)} {(2)}) (C {(grep)} {(-E)} {(SQ <"^[0-9a-f]+$">)}) (C {(sort)}) (C {(uniq)}) ] negated: False ) ] ) left_token: spids: [1149 1217] ) } ] ) } spids: [1145] ) ] spids: [1143] ) (C {(echo)} {(Expected) (Lit_Other ":")} { (BracedVarSub token: bracket_op: (WholeArray op_id:Lit_At) spids: [1231 1236] ) } ) (C {(echo)} {(Actual) (Lit_Other ":")} { (BracedVarSub token: bracket_op: (WholeArray op_id:Lit_At) spids: [1244 1249] ) } ) (C {(check_eq)} { (DQ (BracedVarSub token: prefix_op: VSub_Pound bracket_op: (WholeArray op_id:Lit_At) spids: [1256 1262] ) ) } { (DQ (BracedVarSub token: prefix_op: VSub_Pound bracket_op: (WholeArray op_id:Lit_At) spids: [1266 1272] ) ) } ) (Assignment keyword: Assign_Local pairs: [(assign_pair lhs:(LhsName name:index) op:Equal rhs:{(0)} spids:[1279])] spids: [1277] ) (Assignment keyword: Assign_Local pairs: [(assign_pair lhs:(LhsName name:parent) op:Equal rhs:{(SQ )} spids:[1285])] spids: [1283] ) (While cond: [ (C {(Lit_Other "[")} {(DQ (${ VSub_Name index))} {(-lt)} { (DQ (BracedVarSub token: prefix_op: VSub_Pound bracket_op: (WholeArray op_id:Lit_At) spids: [1301 1307] ) ) } {(Lit_Other "]")} ) ] body: (DoGroup children: [ (C {(check_eq)} { (DQ (BracedVarSub token: bracket_op: (ArrayIndex expr:(ArithWord w:{($ VSub_Name "$index")})) spids: [1323 1328] ) ) } { (DQ (BracedVarSub token: bracket_op: (ArrayIndex expr:(ArithWord w:{($ VSub_Name "$index")})) spids: [1332 1337] ) ) } ) (Assignment keyword: Assign_Local pairs: [ (assign_pair lhs: (LhsName name:layer) op: Equal rhs: { (DQ (BracedVarSub token: bracket_op: (ArrayIndex expr:(ArithWord w:{($ VSub_Name "$index")})) spids: [1350 1355] ) ) } spids: [1348] ) ] spids: [1346] ) (C {(echo)} {(Checking)} {(layer) (Lit_Other ":")} {(DQ (${ VSub_Name layer))}) (Assignment keyword: Assign_Local pairs: [ (assign_pair lhs: (LhsName name:listing) op: Equal rhs: { (DQ (CommandSubPart command_list: (CommandList children: [ (Pipeline children: [ (C {(tar)} {(xOf)} {(DQ (${ VSub_Name test_data))} {(DQ (./) (${ VSub_Name layer) (/layer.tar))} ) (C {(tar)} {(tv)}) ] negated: False ) ] ) left_token: spids: [1383 1407] ) ) } spids: [1381] ) ] spids: [1379] ) (C {(check_eq)} { (DQ (CommandSubPart command_list: (CommandList children: [ (AndOr children: [ (Pipeline children: [ (C {(echo)} {(DQ (${ VSub_Name listing))}) (C {(grep)} {(-Fv)} {(DQ (${ VSub_Name MAGIC_TIMESTAMP))}) ] negated: False ) (C {(true)}) ] op_id: Op_DPipe ) ] ) left_token: spids: [1419 1443] ) ) } {(DQ )} ) (C {(check_id)} {(DQ (${ VSub_Name input))} {(DQ (${ VSub_Name layer))} { (DQ (EscapedLiteralPart token:) (${ VSub_Name layer) (EscapedLiteralPart token: ) ) } ) (If arms: [ (if_arm cond: [ (Sentence child: (DBracket expr: (BoolUnary op_id:BoolUnary_n child:{(DQ (${ VSub_Name parent))}) ) terminator: ) ] action: [ (C {(check_parent)} {(DQ (${ VSub_Name input))} {(DQ (${ VSub_Name layer))} { (DQ (EscapedLiteralPart token:) (${ VSub_Name parent) (EscapedLiteralPart token:) ) } ) ] spids: [-1 1494] ) ] spids: [-1 1520] ) (Assignment keyword: Assign_Local pairs: [ (assign_pair lhs: (LhsName name:layer_size) op: Equal rhs: { (CommandSubPart command_list: (CommandList children: [ (Pipeline children: [ (C {(tar)} {(xOf)} {(DQ (${ VSub_Name test_data))} {(DQ (./) (${ VSub_Name layer) (/layer.tar))} ) (C {(wc)} {(-c)}) (C {(xargs)}) ] negated: False ) ] ) left_token: spids: [1531 1559] ) } spids: [1530] ) ] spids: [1528] ) (C {(check_size)} {(DQ (${ VSub_Name input))} {(DQ (${ VSub_Name layer))} {(DQ (${ VSub_Name layer_size))} ) (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:index) op: Equal rhs: { (ArithSubPart anode: (ArithBinary op_id: Arith_Plus left: (ArithVarRef name:index) right: (ArithWord w:{(Lit_Digits 1)}) ) spids: [1585 1592] ) } spids: [1584] ) ] spids: [1584] ) (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:parent) op: Equal rhs: {($ VSub_Name "$layer")} spids: [1595] ) ] spids: [1595] ) ] spids: [1313 1599] ) ) ] spids: [1045] ) spids: [1039 1044] ) (FuncDef name: check_layers body: (BraceGroup children: [ (Assignment keyword: Assign_Local pairs: [ (assign_pair lhs: (LhsName name:input) op: Equal rhs: {($ VSub_Number "$1")} spids: [1615] ) ] spids: [1613] ) (C {(shift)}) (C {(check_layers_aux)} {(DQ ($ VSub_Name "$input"))} {(DQ ($ VSub_At "$@"))}) (C {(check_layers_aux)} {(DQ (notop_) ($ VSub_Name "$input"))} {(DQ ($ VSub_At "$@"))}) ] spids: [1610] ) spids: [1604 1609] ) (FuncDef name: test_gen_image body: (BraceGroup children: [ (AndOr children: [ (C {(grep)} {(-Fsq)} {(DQ (./gen.out))} {(DQ ($ VSub_Name "$TEST_DATA_DIR") (/gen_image.tar))} ) (C {(fail)} { (DQ ("'./gen.out' not found in '") ($ VSub_Name "$TEST_DATA_DIR") ("/gen_image.tar'") ) } ) ] op_id: Op_DPipe ) ] spids: [1653] ) spids: [1647 1652] ) (FuncDef name: test_dummy_repository body: (BraceGroup children: [ (Assignment keyword: Assign_Local pairs: [ (assign_pair lhs: (LhsName name:layer) op: Equal rhs: {(DQ (0279f3ce8b08d10506abcf452393b3e48439f5eca41b836fae59a0d509fbafea))} spids: [1695] ) ] spids: [1693] ) (Assignment keyword: Assign_Local pairs: [ (assign_pair lhs: (LhsName name:test_data) op: Equal rhs: {(DQ (${ VSub_Name TEST_DATA_DIR) (/dummy_repository.tar))} spids: [1703] ) ] spids: [1701] ) (C {(check_layers_aux)} {(DQ (dummy_repository))} {(DQ ($ VSub_Name "$layer"))}) (Assignment keyword: Assign_Local pairs: [ (assign_pair lhs: (LhsName name:repositories) op: Equal rhs: { (DQ (CommandSubPart command_list: (CommandList children: [ (C {(tar)} {(xOf)} {(DQ (${ VSub_Name test_data))} {(DQ (./repositories))}) ] ) left_token: spids: [1729 1743] ) ) } spids: [1727] ) ] spids: [1725] ) (AndOr children: [ (Pipeline children: [ (C {(echo)} {(DQ (${ VSub_Name repositories))}) (C {(grep)} {(-Esq)} {(--)} { (DQ (EscapedLiteralPart token:) ("gcr.io/dummy/[a-zA-Z_]*_docker_testdata") (EscapedLiteralPart token:) (": {") ) } ) ] negated: False ) (C {(fail)} { (DQ ("Cannot find image in repository gcr.io/dummy in '") (${ VSub_Name repositories) ("'") ) } ) ] op_id: Op_DPipe ) (C {(EXPECT_CONTAINS)} {(DQ (${ VSub_Name repositories))} { (DQ (EscapedLiteralPart token:) (dummy_repository) (EscapedLiteralPart token:) (": ") (EscapedLiteralPart token:) ($ VSub_Name "$layer") (EscapedLiteralPart token:) ) } ) ] spids: [1690] ) spids: [1684 1689] ) (FuncDef name: test_files_base body: (BraceGroup children: [ (C {(check_layers)} {(DQ (files_base))} {(DQ (82ca3945f7d07df82f274d7fafe83fd664c2154e5c64c988916ccd5b217bb710))} ) ] spids: [1818] ) spids: [1812 1817] ) (FuncDef name: test_files_with_files_base body: (BraceGroup children: [ (C {(check_layers)} {(DQ (files_with_files_base))} {(DQ (82ca3945f7d07df82f274d7fafe83fd664c2154e5c64c988916ccd5b217bb710))} {(DQ (84c0d09919ae8b06cb6b064d8cd5eab63341a46f11ccc7ecbe270ad3e1f52744))} ) ] spids: [1842] ) spids: [1836 1841] ) (FuncDef name: test_tar_base body: (BraceGroup children: [ (C {(check_layers)} {(DQ (tar_base))} {(DQ (8b9e4db9dd4b990ee6d8adc2843ad64702ad9063ae6c22e8ca5f94aa54e71277))} ) (C {(check_no_property)} {(DQ (Entrypoint))} {(DQ (tar_base))} {(DQ (8b9e4db9dd4b990ee6d8adc2843ad64702ad9063ae6c22e8ca5f94aa54e71277))} ) ] spids: [1872] ) spids: [1866 1871] ) (FuncDef name: test_tar_with_tar_base body: (BraceGroup children: [ (C {(check_layers)} {(DQ (tar_with_tar_base))} {(DQ (8b9e4db9dd4b990ee6d8adc2843ad64702ad9063ae6c22e8ca5f94aa54e71277))} {(DQ (1cc81a2aaec2e3727d98d48bf9ba09d3ac96ef48adf5edae861d15dd0191dc40))} ) ] spids: [1922] ) spids: [1916 1921] ) (FuncDef name: test_directory_with_tar_base body: (BraceGroup children: [ (C {(check_layers)} {(DQ (directory_with_tar_base))} {(DQ (8b9e4db9dd4b990ee6d8adc2843ad64702ad9063ae6c22e8ca5f94aa54e71277))} {(DQ (e56ddeb8279698484f50d480f71cb5380223ad0f451766b7b9a9348129d02542))} ) ] spids: [1952] ) spids: [1946 1951] ) (FuncDef name: test_files_with_tar_base body: (BraceGroup children: [ (C {(check_layers)} {(DQ (files_with_tar_base))} {(DQ (8b9e4db9dd4b990ee6d8adc2843ad64702ad9063ae6c22e8ca5f94aa54e71277))} {(DQ (f099727fa58f9b688e77b511b3cc728b86ae0e84d197b9330bd51082ad5589f2))} ) ] spids: [1982] ) spids: [1976 1981] ) (FuncDef name: test_workdir_with_tar_base body: (BraceGroup children: [ (C {(check_layers)} {(DQ (workdir_with_tar_base))} {(DQ (8b9e4db9dd4b990ee6d8adc2843ad64702ad9063ae6c22e8ca5f94aa54e71277))} {(DQ (f24cbe53bd1b78909c6dba0bd47016354f3488b35b85aeee68ecc423062b927e))} ) ] spids: [2012] ) spids: [2006 2011] ) (FuncDef name: test_tar_with_files_base body: (BraceGroup children: [ (C {(check_layers)} {(DQ (tar_with_files_base))} {(DQ (82ca3945f7d07df82f274d7fafe83fd664c2154e5c64c988916ccd5b217bb710))} {(DQ (bee1a325e4b51a1dcfd7e447987b4e130590815865ab22e8744878053d525f20))} ) ] spids: [2042] ) spids: [2036 2041] ) (FuncDef name: test_base_with_entrypoint body: (BraceGroup children: [ (C {(check_layers)} {(DQ (base_with_entrypoint))} {(DQ (4acbeb0495918726c0107e372b421e1d2a6fd4825d58fc3f0b0b2a719fb3ce1b))} ) (C {(check_entrypoint)} {(DQ (base_with_entrypoint))} {(DQ (4acbeb0495918726c0107e372b421e1d2a6fd4825d58fc3f0b0b2a719fb3ce1b))} {(SQ <"[\"/bar\"]">)} ) (C {(check_ports)} {(DQ (base_with_entrypoint))} {(DQ (4acbeb0495918726c0107e372b421e1d2a6fd4825d58fc3f0b0b2a719fb3ce1b))} {(SQ <"{\"8080/tcp\": {}}">)} ) ] spids: [2072] ) spids: [2066 2071] ) (FuncDef name: test_derivative_with_shadowed_cmd body: (BraceGroup children: [ (C {(check_layers)} {(DQ (derivative_with_shadowed_cmd))} {(DQ (4acbeb0495918726c0107e372b421e1d2a6fd4825d58fc3f0b0b2a719fb3ce1b))} {(DQ (e35f57dc6c1e84ae67dcaaf3479a3a3c0f52ac4d194073bd6214e04c05beab42))} ) ] spids: [2140] ) spids: [2134 2139] ) (FuncDef name: test_derivative_with_cmd body: (BraceGroup children: [ (C {(check_layers)} {(DQ (derivative_with_cmd))} {(DQ (4acbeb0495918726c0107e372b421e1d2a6fd4825d58fc3f0b0b2a719fb3ce1b))} {(DQ (e35f57dc6c1e84ae67dcaaf3479a3a3c0f52ac4d194073bd6214e04c05beab42))} {(DQ (186289545131e34510006ac79498078dcf41736a5eb9a36920a6b30d3f45bc01))} ) (C {(check_entrypoint)} {(DQ (derivative_with_cmd))} {(DQ (186289545131e34510006ac79498078dcf41736a5eb9a36920a6b30d3f45bc01))} {(SQ <"[\"/bar\"]">)} ) (C {(check_cmd)} {(DQ (derivative_with_cmd))} {(DQ (e35f57dc6c1e84ae67dcaaf3479a3a3c0f52ac4d194073bd6214e04c05beab42))} {(SQ <"[\"shadowed-arg\"]">)} ) (C {(check_cmd)} {(DQ (derivative_with_cmd))} {(DQ (186289545131e34510006ac79498078dcf41736a5eb9a36920a6b30d3f45bc01))} {(SQ <"[\"arg1\", \"arg2\"]">)} ) (C {(check_ports)} {(DQ (derivative_with_cmd))} {(DQ (186289545131e34510006ac79498078dcf41736a5eb9a36920a6b30d3f45bc01))} {(SQ <"{\"80/tcp\": {}, \"8080/tcp\": {}}">)} ) ] spids: [2170] ) spids: [2164 2169] ) (FuncDef name: test_derivative_with_volume body: (BraceGroup children: [ (C {(check_layers)} {(DQ (derivative_with_volume))} {(DQ (125e7cfb9d4a6d803a57b88bcdb05d9a6a47ac0d6312a8b4cff52a2685c5c858))} {(DQ (08424283ad3a7e020e210bec22b166d7ebba57f7ba2d0713c2fd7bd1e2038f88))} ) (C {(check_volumes)} {(DQ (derivative_with_volume))} {(DQ (125e7cfb9d4a6d803a57b88bcdb05d9a6a47ac0d6312a8b4cff52a2685c5c858))} {(SQ <"{\"/logs\": {}}">)} ) (C {(check_volumes)} {(DQ (derivative_with_volume))} {(DQ (08424283ad3a7e020e210bec22b166d7ebba57f7ba2d0713c2fd7bd1e2038f88))} {(SQ <"{\"/asdf\": {}, \"/blah\": {}, \"/logs\": {}}">)} ) ] spids: [2302] ) spids: [2296 2301] ) (FuncDef name: test_generated_tarball body: (BraceGroup children: [ (C {(check_layers)} {(DQ (generated_tarball))} {(DQ (54b8328604115255cc76c12a2a51939be65c40bf182ff5a898a5fb57c38f7772))} ) ] spids: [2380] ) spids: [2374 2379] ) (FuncDef name: test_with_env body: (BraceGroup children: [ (C {(check_layers)} {(DQ (with_env))} {(DQ (125e7cfb9d4a6d803a57b88bcdb05d9a6a47ac0d6312a8b4cff52a2685c5c858))} {(DQ (42a1bd0f449f61a23b8a7776875ffb6707b34ee99c87d6428a7394f5e55e8624))} ) (C {(check_env)} {(DQ (with_env))} {(DQ (42a1bd0f449f61a23b8a7776875ffb6707b34ee99c87d6428a7394f5e55e8624))} {(SQ <"[\"bar=blah blah blah\", \"foo=/asdf\"]">)} ) ] spids: [2404] ) spids: [2398 2403] ) (FuncDef name: test_with_double_env body: (BraceGroup children: [ (C {(check_layers)} {(DQ (with_double_env))} {(DQ (125e7cfb9d4a6d803a57b88bcdb05d9a6a47ac0d6312a8b4cff52a2685c5c858))} {(DQ (42a1bd0f449f61a23b8a7776875ffb6707b34ee99c87d6428a7394f5e55e8624))} {(DQ (576a9fd9c690be04dc7aacbb9dbd1f14816e32dbbcc510f4d42325bbff7163dd))} ) (C {(check_env)} {(DQ (with_double_env))} {(DQ (576a9fd9c690be04dc7aacbb9dbd1f14816e32dbbcc510f4d42325bbff7163dd))} {(SQ <"[\"bar=blah blah blah\", \"baz=/asdf blah blah blah\", \"foo=/asdf\"]">)} ) ] spids: [2454] ) spids: [2448 2453] ) (FuncDef name: test_with_label body: (BraceGroup children: [ (C {(check_layers)} {(DQ (with_label))} {(DQ (125e7cfb9d4a6d803a57b88bcdb05d9a6a47ac0d6312a8b4cff52a2685c5c858))} {(DQ (eba6abda3d259ab6ed5f4d48b76df72a5193fad894d4ae78fbf0a363d8f9e8fd))} ) (C {(check_label)} {(DQ (with_label))} {(DQ (eba6abda3d259ab6ed5f4d48b76df72a5193fad894d4ae78fbf0a363d8f9e8fd))} { (SQ < "[\"com.example.bar={\\\"name\\\": \\\"blah\\\"}\", \"com.example.baz=qux\", \"com.example.foo={\\\"name\\\": \\\"blah\\\"}\"]" > ) } ) ] spids: [2514] ) spids: [2508 2513] ) (FuncDef name: test_with_double_label body: (BraceGroup children: [ (C {(check_layers)} {(DQ (with_double_label))} {(DQ (125e7cfb9d4a6d803a57b88bcdb05d9a6a47ac0d6312a8b4cff52a2685c5c858))} {(DQ (eba6abda3d259ab6ed5f4d48b76df72a5193fad894d4ae78fbf0a363d8f9e8fd))} {(DQ (bfe88fbb5e24fc5bff138f7a1923d53a2ee1bbc8e54b6f5d9c371d5f48b6b023))} ) (C {(check_label)} {(DQ (with_double_label))} {(DQ (bfe88fbb5e24fc5bff138f7a1923d53a2ee1bbc8e54b6f5d9c371d5f48b6b023))} { (SQ < "[\"com.example.bar={\\\"name\\\": \\\"blah\\\"}\", \"com.example.baz=qux\", \"com.example.foo={\\\"name\\\": \\\"blah\\\"}\", \"com.example.qux={\\\"name\\\": \\\"blah-blah\\\"}\"]" > ) } ) ] spids: [2564] ) spids: [2558 2563] ) (FuncDef name: test_with_user body: (BraceGroup children: [ (C {(check_user)} {(DQ (with_user))} {(DQ (65664d4d78ff321684e2a8bf165792ce562c5990c9ba992e6288dcb1ec7f675c))} { (DQ (EscapedLiteralPart token:) (nobody) (EscapedLiteralPart token:) ) } ) ] spids: [2621] ) spids: [2615 2620] ) (FuncDef name: get_layer_listing body: (BraceGroup children: [ (Assignment keyword: Assign_Local pairs: [ (assign_pair lhs: (LhsName name:input) op: Equal rhs: {($ VSub_Number "$1")} spids: [2658] ) ] spids: [2656] ) (Assignment keyword: Assign_Local pairs: [ (assign_pair lhs: (LhsName name:layer) op: Equal rhs: {($ VSub_Number "$2")} spids: [2664] ) ] spids: [2662] ) (Assignment keyword: Assign_Local pairs: [ (assign_pair lhs: (LhsName name:test_data) op: Equal rhs: {(DQ (${ VSub_Name TEST_DATA_DIR) (/) (${ VSub_Name input) (.tar))} spids: [2670] ) ] spids: [2668] ) (Pipeline children: [ (C {(tar)} {(xOf)} {(DQ (${ VSub_Name test_data))} {(DQ (./) (${ VSub_Name layer) (/layer.tar))} ) (C {(tar)} {(tv)}) (C {(sed)} {(-e)} {(SQ <"s/^.*:00 //">)}) ] negated: False ) ] spids: [2653] ) spids: [2647 2652] ) (FuncDef name: test_data_path body: (BraceGroup children: [ (Assignment keyword: Assign_Local pairs: [ (assign_pair lhs: (LhsName name:no_data_path_sha) op: Equal rhs: {(DQ (451d182e5c71840f00ba9726dc0239db73a21b7e89e79c77f677e3f7c5c23d44))} spids: [2733] ) ] spids: [2731] ) (Assignment keyword: Assign_Local pairs: [ (assign_pair lhs: (LhsName name:data_path_sha) op: Equal rhs: {(DQ (9a41c9e1709558f7ef06f28f66e9056feafa7e0f83990801e1b27c987278d8e8))} spids: [2741] ) ] spids: [2739] ) (Assignment keyword: Assign_Local pairs: [ (assign_pair lhs: (LhsName name:absolute_data_path_sha) op: Equal rhs: {(DQ (f196c42ab4f3eb850d9655b950b824db2c99c01527703ac486a7b48bb2a34f44))} spids: [2749] ) ] spids: [2747] ) (Assignment keyword: Assign_Local pairs: [ (assign_pair lhs: (LhsName name:root_data_path_sha) op: Equal rhs: {(DQ (19d7fd26d67bfaeedd6232dcd441f14ee163bc81c56ed565cc20e73311c418b6))} spids: [2757] ) ] spids: [2755] ) (C {(check_layers_aux)} {(DQ (no_data_path_image))} {(DQ (${ VSub_Name no_data_path_sha))}) (C {(check_layers_aux)} {(DQ (data_path_image))} {(DQ (${ VSub_Name data_path_sha))}) (C {(check_layers_aux)} {(DQ (absolute_data_path_image))} {(DQ (${ VSub_Name absolute_data_path_sha))} ) (C {(check_layers_aux)} {(DQ (root_data_path_image))} {(DQ (${ VSub_Name root_data_path_sha))} ) (C {(check_eq)} { (DQ (CommandSubPart command_list: (CommandList children: [ (C {(get_layer_listing)} {(DQ (no_data_path_image))} {(DQ (${ VSub_Name no_data_path_sha))} ) ] ) left_token: spids: [2836 2848] ) ) } {(SQ <"./\n"> <./test>)} ) (C {(check_eq)} { (DQ (CommandSubPart command_list: (CommandList children: [ (C {(get_layer_listing)} {(DQ (data_path_image))} {(DQ (${ VSub_Name data_path_sha))} ) ] ) left_token: spids: [2862 2874] ) ) } {(SQ <"./\n"> <"./test/\n"> <./test/test>)} ) (C {(check_eq)} { (DQ (CommandSubPart command_list: (CommandList children: [ (C {(get_layer_listing)} {(DQ (absolute_data_path_image))} {(DQ (${ VSub_Name absolute_data_path_sha))} ) ] ) left_token: spids: [2910 2922] ) ) } { (SQ <"./\n"> <"./docker/\n"> <"./docker/testdata/\n"> <"./docker/testdata/test/\n"> <./docker/testdata/test/test> ) } ) (C {(check_eq)} { (DQ (CommandSubPart command_list: (CommandList children: [ (C {(get_layer_listing)} {(DQ (root_data_path_image))} {(DQ (${ VSub_Name root_data_path_sha))} ) ] ) left_token: spids: [2948 2960] ) ) } { (DQ ("./\n") ("./tools/\n") ("./tools/build_defs/\n") ("./tools/build_defs/docker/\n") ("./tools/build_defs/docker/testdata/\n") ("./tools/build_defs/docker/testdata/test/\n") (./tools/build_defs/docker/testdata/test/test) ) } ) ] spids: [2728] ) spids: [2722 2727] ) (FuncDef name: test_extras_with_deb body: (BraceGroup children: [ (Assignment keyword: Assign_Local pairs: [ (assign_pair lhs: (LhsName name:test_data) op: Equal rhs: {(DQ (${ VSub_Name TEST_DATA_DIR) (/extras_with_deb.tar))} spids: [2989] ) ] spids: [2987] ) (Assignment keyword: Assign_Local pairs: [ (assign_pair lhs: (LhsName name:sha) op: Equal rhs: { (CommandSubPart command_list: (CommandList children: [(C {(tar)} {(xOf)} {(${ VSub_Name test_data)} {(./top)})] ) left_token: spids: [3001 3011] ) } spids: [3000] ) ] spids: [2998] ) (Assignment keyword: Assign_Local pairs: [ (assign_pair lhs: (LhsName name:layer_listing) op: Equal rhs: { (DQ (CommandSubPart command_list: (CommandList children: [ (Pipeline children: [ (C {(get_layer_listing)} {(DQ (extras_with_deb))} {(DQ (${ VSub_Name sha))} ) (C {(sort)}) ] negated: False ) ] ) left_token: spids: [3023 3039] ) ) } spids: [3021] ) ] spids: [3019] ) (C {(check_eq)} {(DQ (${ VSub_Name layer_listing))} { (DQ ("./\n") ("./etc/\n") ("./etc/nsswitch.conf\n") ("./tmp/\n") ("./usr/\n") ("./usr/bin/\n") ("./usr/bin/java -> /path/to/bin/java\n") (./usr/titi) ) } ) ] spids: [2984] ) spids: [2978 2983] ) (C {(run_suite)} {(DQ (build_test))}) ] )