// Copyright 2015 CoreOS, Inc. // // 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 unit import ( "testing" ) func TestUnitNameEscape(t *testing.T) { tests := []struct { in string out string isPath bool }{ // turn empty string path into escaped / { in: "", out: "-", isPath: true, }, // turn redundant ////s into single escaped / { in: "/////////", out: "-", isPath: true, }, // remove all redundant ////s { in: "///foo////bar/////tail//////", out: "foo-bar-tail", isPath: true, }, // leave empty string empty { in: "", out: "", isPath: false, }, // escape leading dot { in: ".", out: `\x2e`, isPath: true, }, // escape leading dot { in: "/.", out: `\x2e`, isPath: true, }, // escape leading dot { in: "/////////.", out: `\x2e`, isPath: true, }, // escape leading dot { in: "/////////.///////////////", out: `\x2e`, isPath: true, }, // escape leading dot { in: ".....", out: `\x2e....`, isPath: true, }, // escape leading dot { in: "/.foo/.bar", out: `\x2efoo-.bar`, isPath: true, }, // escape leading dot { in: ".foo/.bar", out: `\x2efoo-.bar`, isPath: true, }, // escape leading dot { in: ".foo/.bar", out: `\x2efoo-.bar`, isPath: false, }, // escape disallowed { in: `///..\-!#??///`, out: `---..\x5c\x2d\x21\x23\x3f\x3f---`, isPath: false, }, // escape disallowed { in: `///..\-!#??///`, out: `\x2e.\x5c\x2d\x21\x23\x3f\x3f`, isPath: true, }, // escape real-world example { in: `user-cloudinit@/var/lib/coreos/vagrant/vagrantfile-user-data.service`, out: `user\x2dcloudinit\x40-var-lib-coreos-vagrant-vagrantfile\x2duser\x2ddata.service`, isPath: false, }, } for i, tt := range tests { var s string if tt.isPath { s = UnitNamePathEscape(tt.in) } else { s = UnitNameEscape(tt.in) } if s != tt.out { t.Errorf("case %d: failed escaping %v isPath: %v - expected %v, got %v", i, tt.in, tt.isPath, tt.out, s) } } } func TestUnitNameUnescape(t *testing.T) { tests := []struct { in string out string isPath bool }{ // turn empty string path into / { in: "", out: "/", isPath: true, }, // leave empty string empty { in: "", out: "", isPath: false, }, // turn ////s into { in: "---------", out: "/////////", isPath: true, }, // unescape hex { in: `---..\x5c\x2d\x21\x23\x3f\x3f---`, out: `///..\-!#??///`, isPath: false, }, // unescape hex { in: `\x2e.\x5c\x2d\x21\x23\x3f\x3f`, out: `/..\-!#??`, isPath: true, }, // unescape hex, retain invalids { in: `\x2e.\x5c\x2d\xaZ\x.o\x21\x23\x3f\x3f`, out: `/..\-\xaZ\x.o!#??`, isPath: true, }, // unescape hex, retain invalids, partial tail { in: `\x2e.\x5c\x\x2d\xaZ\x.o\x21\x23\x3f\x3f\x3`, out: `/..\\x-\xaZ\x.o!#??\x3`, isPath: true, }, // unescape hex, retain invalids, partial tail { in: `\x2e.\x5c\x\x2d\xaZ\x.o\x21\x23\x3f\x3f\x`, out: `/..\\x-\xaZ\x.o!#??\x`, isPath: true, }, // unescape hex, retain invalids, partial tail { in: `\x2e.\x5c\x\x2d\xaZ\x.o\x21\x23\x3f\x3f\`, out: `/..\\x-\xaZ\x.o!#??\`, isPath: true, }, // unescape real-world example { in: `user\x2dcloudinit\x40-var-lib-coreos-vagrant-vagrantfile\x2duser\x2ddata.service`, out: `user-cloudinit@/var/lib/coreos/vagrant/vagrantfile-user-data.service`, isPath: false, }, } for i, tt := range tests { var s string if tt.isPath { s = UnitNamePathUnescape(tt.in) } else { s = UnitNameUnescape(tt.in) } if s != tt.out { t.Errorf("case %d: failed unescaping %v isPath: %v - expected %v, got %v", i, tt.in, tt.isPath, tt.out, s) } } }