podman
1//go:build !remote
2
3package generate4
5import (6"testing"7
8"github.com/containers/common/libnetwork/types"9"github.com/stretchr/testify/assert"10)
11
12func TestParsePortMappingWithHostPort(t *testing.T) {13tests := []struct {14name string15arg []types.PortMapping16arg2 map[uint16][]string17want []types.PortMapping18}{19{20name: "no ports",21arg: nil,22want: nil,23},24{25name: "one tcp port",26arg: []types.PortMapping{27{28HostPort: 8080,29ContainerPort: 80,30Protocol: "tcp",31},32},33want: []types.PortMapping{34{35HostPort: 8080,36ContainerPort: 80,37Protocol: "tcp",38Range: 1,39},40},41},42{43name: "one tcp port no proto",44arg: []types.PortMapping{45{46HostPort: 8080,47ContainerPort: 80,48},49},50want: []types.PortMapping{51{52HostPort: 8080,53ContainerPort: 80,54Protocol: "tcp",55Range: 1,56},57},58},59{60name: "one udp port",61arg: []types.PortMapping{62{63HostPort: 8080,64ContainerPort: 80,65Protocol: "udp",66},67},68want: []types.PortMapping{69{70HostPort: 8080,71ContainerPort: 80,72Protocol: "udp",73Range: 1,74},75},76},77{78name: "one sctp port",79arg: []types.PortMapping{80{81HostPort: 8080,82ContainerPort: 80,83Protocol: "sctp",84},85},86want: []types.PortMapping{87{88HostPort: 8080,89ContainerPort: 80,90Protocol: "sctp",91Range: 1,92},93},94},95{96name: "one port two protocols",97arg: []types.PortMapping{98{99HostPort: 8080,100ContainerPort: 80,101Protocol: "tcp,udp",102},103},104want: []types.PortMapping{105{106HostPort: 8080,107ContainerPort: 80,108Protocol: "tcp",109Range: 1,110},111{112HostPort: 8080,113ContainerPort: 80,114Protocol: "udp",115Range: 1,116},117},118},119{120name: "one port three protocols",121arg: []types.PortMapping{122{123HostPort: 8080,124ContainerPort: 80,125Protocol: "tcp,udp,sctp",126},127},128want: []types.PortMapping{129{130HostPort: 8080,131ContainerPort: 80,132Protocol: "tcp",133Range: 1,134},135{136HostPort: 8080,137ContainerPort: 80,138Protocol: "udp",139Range: 1,140},141{142HostPort: 8080,143ContainerPort: 80,144Protocol: "sctp",145Range: 1,146},147},148},149{150name: "one port with range 1",151arg: []types.PortMapping{152{153HostPort: 8080,154ContainerPort: 80,155Protocol: "tcp",156Range: 1,157},158},159want: []types.PortMapping{160{161HostPort: 8080,162ContainerPort: 80,163Protocol: "tcp",164Range: 1,165},166},167},168{169name: "one port with range 5",170arg: []types.PortMapping{171{172HostPort: 8080,173ContainerPort: 80,174Protocol: "tcp",175Range: 5,176},177},178want: []types.PortMapping{179{180HostPort: 8080,181ContainerPort: 80,182Protocol: "tcp",183Range: 5,184},185},186},187{188name: "two ports joined",189arg: []types.PortMapping{190{191HostPort: 8080,192ContainerPort: 80,193Protocol: "tcp",194},195{196HostPort: 8081,197ContainerPort: 81,198Protocol: "tcp",199},200},201want: []types.PortMapping{202{203HostPort: 8080,204ContainerPort: 80,205Protocol: "tcp",206Range: 2,207},208},209},210{211name: "two ports joined with range",212arg: []types.PortMapping{213{214HostPort: 8080,215ContainerPort: 80,216Protocol: "tcp",217Range: 2,218},219{220HostPort: 8081,221ContainerPort: 81,222Protocol: "tcp",223},224},225want: []types.PortMapping{226{227HostPort: 8080,228ContainerPort: 80,229Protocol: "tcp",230Range: 2,231},232},233},234{235name: "two ports with no overlapping range",236arg: []types.PortMapping{237{238HostPort: 8080,239ContainerPort: 80,240Protocol: "tcp",241Range: 10,242},243{244HostPort: 9090,245ContainerPort: 9090,246Protocol: "tcp",247},248},249want: []types.PortMapping{250{251HostPort: 9090,252ContainerPort: 9090,253Protocol: "tcp",254Range: 1,255},256{257HostPort: 8080,258ContainerPort: 80,259Protocol: "tcp",260Range: 10,261},262},263},264{265name: "four ports with two overlapping ranges",266arg: []types.PortMapping{267{268HostPort: 8080,269ContainerPort: 80,270Protocol: "tcp",271Range: 10,272},273{274HostPort: 8085,275ContainerPort: 85,276Protocol: "tcp",277Range: 10,278},279{280HostPort: 100,281ContainerPort: 5,282Protocol: "tcp",283},284{285HostPort: 101,286ContainerPort: 6,287Protocol: "tcp",288},289},290want: []types.PortMapping{291{292HostPort: 8080,293ContainerPort: 80,294Protocol: "tcp",295Range: 15,296},297{298HostPort: 100,299ContainerPort: 5,300Protocol: "tcp",301Range: 2,302},303},304},305{306name: "two overlapping ranges",307arg: []types.PortMapping{308{309HostPort: 8080,310ContainerPort: 80,311Protocol: "tcp",312Range: 10,313},314{315HostPort: 8085,316ContainerPort: 85,317Protocol: "tcp",318Range: 2,319},320},321want: []types.PortMapping{322{323HostPort: 8080,324ContainerPort: 80,325Protocol: "tcp",326Range: 10,327},328},329},330{331name: "four overlapping ranges",332arg: []types.PortMapping{333{334HostPort: 8080,335ContainerPort: 80,336Protocol: "tcp",337Range: 10,338},339{340HostPort: 8085,341ContainerPort: 85,342Protocol: "tcp",343Range: 2,344},345{346HostPort: 8090,347ContainerPort: 90,348Protocol: "tcp",349Range: 7,350},351{352HostPort: 8095,353ContainerPort: 95,354Protocol: "tcp",355},356},357want: []types.PortMapping{358{359HostPort: 8080,360ContainerPort: 80,361Protocol: "tcp",362Range: 17,363},364},365},366{367name: "one port range overlaps 5 ports",368arg: []types.PortMapping{369{370HostPort: 8080,371ContainerPort: 80,372Range: 20,373},374{375HostPort: 8085,376ContainerPort: 85,377Range: 2,378},379{380HostPort: 8090,381ContainerPort: 90,382},383{384HostPort: 8095,385ContainerPort: 95,386},387{388HostPort: 8096,389ContainerPort: 96,390},391},392want: []types.PortMapping{393{394HostPort: 8080,395ContainerPort: 80,396Protocol: "tcp",397Range: 20,398},399},400},401{402name: "different host ip same port",403arg: []types.PortMapping{404{405HostPort: 8080,406ContainerPort: 80,407Protocol: "tcp",408HostIP: "192.168.1.1",409},410{411HostPort: 8080,412ContainerPort: 80,413Protocol: "tcp",414HostIP: "192.168.2.1",415},416},417want: []types.PortMapping{418{419HostPort: 8080,420ContainerPort: 80,421Protocol: "tcp",422HostIP: "192.168.1.1",423Range: 1,424},425{426HostPort: 8080,427ContainerPort: 80,428Protocol: "tcp",429HostIP: "192.168.2.1",430Range: 1,431},432},433},434}435for _, tt := range tests {436tt := tt437t.Run(tt.name, func(t *testing.T) {438got, err := ParsePortMapping(tt.arg, tt.arg2)439assert.NoError(t, err, "error is not nil")440// use ElementsMatch instead of Equal because the order is not consistent441assert.ElementsMatch(t, tt.want, got, "got unexpected port mapping")442})443}444}
445
446func TestParsePortMappingWithoutHostPort(t *testing.T) {447tests := []struct {448name string449arg []types.PortMapping450arg2 map[uint16][]string451want []types.PortMapping452}{453{454name: "one tcp port",455arg: []types.PortMapping{456{457HostPort: 0,458ContainerPort: 80,459Protocol: "tcp",460},461},462want: []types.PortMapping{463{464HostPort: 0,465ContainerPort: 80,466Protocol: "tcp",467Range: 1,468},469},470},471{472name: "one port with two protocols",473arg: []types.PortMapping{474{475HostPort: 0,476ContainerPort: 80,477Protocol: "tcp,udp",478},479},480want: []types.PortMapping{481{482HostPort: 0,483ContainerPort: 80,484Protocol: "tcp",485Range: 1,486},487{488HostPort: 0,489ContainerPort: 80,490Protocol: "udp",491Range: 1,492},493},494},495{496name: "same port twice",497arg: []types.PortMapping{498{499HostPort: 0,500ContainerPort: 80,501Protocol: "tcp",502},503{504HostPort: 0,505ContainerPort: 80,506Protocol: "tcp",507},508},509want: []types.PortMapping{510{511HostPort: 0,512ContainerPort: 80,513Protocol: "tcp",514Range: 1,515},516},517},518{519name: "neighbor ports are not joined",520arg: []types.PortMapping{521{522HostPort: 0,523ContainerPort: 80,524Protocol: "tcp",525},526{527HostPort: 0,528ContainerPort: 81,529Protocol: "tcp",530},531},532want: []types.PortMapping{533{534HostPort: 0,535ContainerPort: 80,536Protocol: "tcp",537Range: 1,538},539{540HostPort: 0,541ContainerPort: 81,542Protocol: "tcp",543Range: 1,544},545},546},547{548name: "overlapping range ports are joined",549arg: []types.PortMapping{550{551HostPort: 0,552ContainerPort: 80,553Protocol: "tcp",554Range: 2,555},556{557HostPort: 0,558ContainerPort: 81,559Protocol: "tcp",560},561},562want: []types.PortMapping{563{564HostPort: 0,565ContainerPort: 80,566Protocol: "tcp",567Range: 2,568},569},570},571{572name: "four overlapping range ports are joined",573arg: []types.PortMapping{574{575HostPort: 0,576ContainerPort: 80,577Protocol: "tcp",578Range: 3,579},580{581HostPort: 0,582ContainerPort: 81,583Protocol: "tcp",584},585{586HostPort: 0,587ContainerPort: 82,588Protocol: "tcp",589Range: 10,590},591{592HostPort: 0,593ContainerPort: 90,594Protocol: "tcp",595Range: 5,596},597},598want: []types.PortMapping{599{600HostPort: 0,601ContainerPort: 80,602Protocol: "tcp",603Range: 15,604},605},606},607{608name: "expose one tcp port",609arg2: map[uint16][]string{6108080: {"tcp"},611},612want: []types.PortMapping{613{614HostPort: 0,615ContainerPort: 8080,616Protocol: "tcp",617Range: 1,618},619},620},621{622name: "expose already defined port",623arg: []types.PortMapping{624{625HostPort: 0,626ContainerPort: 8080,627Protocol: "tcp",628},629},630arg2: map[uint16][]string{6318080: {"tcp"},632},633want: []types.PortMapping{634{635HostPort: 0,636ContainerPort: 8080,637Protocol: "tcp",638Range: 1,639},640},641},642{643name: "expose different proto",644arg: []types.PortMapping{645{646HostPort: 0,647ContainerPort: 8080,648Protocol: "tcp",649},650},651arg2: map[uint16][]string{6528080: {"udp"},653},654want: []types.PortMapping{655{656HostPort: 0,657ContainerPort: 8080,658Protocol: "tcp",659Range: 1,660},661{662HostPort: 0,663ContainerPort: 8080,664Protocol: "udp",665Range: 1,666},667},668},669}670for _, tt := range tests {671tt := tt672t.Run(tt.name, func(t *testing.T) {673got, err := ParsePortMapping(tt.arg, tt.arg2)674assert.NoError(t, err, "error is not nil")675
676// because we always get random host ports when it is set to 0 we cannot check that exactly677// check if it is not 0 and set to 0 afterwards678for i := range got {679assert.Greater(t, got[i].HostPort, uint16(0), "host port is zero")680got[i].HostPort = 0681}682
683// use ElementsMatch instead of Equal because the order is not consistent684assert.ElementsMatch(t, tt.want, got, "got unexpected port mapping")685})686}687}
688
689func TestParsePortMappingMixedHostPort(t *testing.T) {690tests := []struct {691name string692arg []types.PortMapping693want []types.PortMapping694resetHostPorts []int695}{696{697name: "two ports one without a hostport set",698arg: []types.PortMapping{699{700HostPort: 0,701ContainerPort: 80,702},703{704HostPort: 8080,705ContainerPort: 8080,706},707},708want: []types.PortMapping{709{710HostPort: 8080,711ContainerPort: 8080,712Protocol: "tcp",713Range: 1,714},715{716HostPort: 0,717ContainerPort: 80,718Protocol: "tcp",719Range: 1,720},721},722resetHostPorts: []int{1},723},724{725name: "two ports one without a hostport set, inverted order",726arg: []types.PortMapping{727{728HostPort: 8080,729ContainerPort: 8080,730},731{732HostPort: 0,733ContainerPort: 80,734},735},736want: []types.PortMapping{737{738HostPort: 8080,739ContainerPort: 8080,740Protocol: "tcp",741Range: 1,742},743{744HostPort: 0,745ContainerPort: 80,746Protocol: "tcp",747Range: 1,748},749},750resetHostPorts: []int{1},751},752{753name: "three ports without host ports, one with a hostport set, , inverted order",754arg: []types.PortMapping{755{756HostPort: 0,757ContainerPort: 80,758},759{760HostPort: 0,761ContainerPort: 85,762},763{764HostPort: 0,765ContainerPort: 90,766},767{768HostPort: 8080,769ContainerPort: 8080,770},771},772want: []types.PortMapping{773{774HostPort: 8080,775ContainerPort: 8080,776Protocol: "tcp",777Range: 1,778},779{780HostPort: 0,781ContainerPort: 80,782Protocol: "tcp",783Range: 1,784},785{786HostPort: 0,787ContainerPort: 85,788Protocol: "tcp",789Range: 1,790},791{792HostPort: 0,793ContainerPort: 90,794Protocol: "tcp",795Range: 1,796},797},798resetHostPorts: []int{1, 2, 3},799},800{801name: "three ports without host ports, one with a hostport set",802arg: []types.PortMapping{803{804HostPort: 8080,805ContainerPort: 8080,806},807{808HostPort: 0,809ContainerPort: 90,810},811{812HostPort: 0,813ContainerPort: 85,814},815{816HostPort: 0,817ContainerPort: 80,818},819},820want: []types.PortMapping{821{822HostPort: 8080,823ContainerPort: 8080,824Protocol: "tcp",825Range: 1,826},827{828HostPort: 0,829ContainerPort: 80,830Protocol: "tcp",831Range: 1,832},833{834HostPort: 0,835ContainerPort: 85,836Protocol: "tcp",837Range: 1,838},839{840HostPort: 0,841ContainerPort: 90,842Protocol: "tcp",843Range: 1,844},845},846resetHostPorts: []int{1, 2, 3},847},848}849for _, tt := range tests {850tt := tt851t.Run(tt.name, func(t *testing.T) {852got, err := ParsePortMapping(tt.arg, nil)853assert.NoError(t, err, "error is not nil")854
855// because we always get random host ports when it is set to 0 we cannot check that exactly856// use resetHostPorts to know which port element is 0857for _, num := range tt.resetHostPorts {858assert.Greater(t, got[num].HostPort, uint16(0), "host port is zero")859got[num].HostPort = 0860}861
862assert.Equal(t, tt.want, got, "got unexpected port mapping")863})864}865}
866
867func TestParsePortMappingError(t *testing.T) {868tests := []struct {869name string870arg []types.PortMapping871err string872}{873{874name: "container port is 0",875arg: []types.PortMapping{876{877HostPort: 8080,878ContainerPort: 0,879Protocol: "tcp",880},881},882err: "container port number must be non-0",883},884{885name: "container port range exceeds max",886arg: []types.PortMapping{887{888HostPort: 8080,889ContainerPort: 65000,890Protocol: "tcp",891Range: 10000,892},893},894err: "container port range exceeds maximum allowable port number",895},896{897name: "host port range exceeds max",898arg: []types.PortMapping{899{900HostPort: 60000,901ContainerPort: 1,902Protocol: "tcp",903Range: 10000,904},905},906err: "host port range exceeds maximum allowable port number",907},908{909name: "invalid protocol",910arg: []types.PortMapping{911{912HostPort: 8080,913ContainerPort: 80,914Protocol: "1",915},916},917err: "unrecognized protocol \"1\" in port mapping",918},919{920name: "invalid protocol 2",921arg: []types.PortMapping{922{923HostPort: 8080,924ContainerPort: 80,925Protocol: "udp,u",926},927},928err: "unrecognized protocol \"u\" in port mapping",929},930{931name: "invalid ip address",932arg: []types.PortMapping{933{934HostPort: 8080,935ContainerPort: 80,936HostIP: "blah",937},938},939err: "invalid IP address \"blah\" in port mapping",940},941{942name: "invalid overalpping range",943arg: []types.PortMapping{944{945HostPort: 8080,946ContainerPort: 80,947Range: 5,948},949{950HostPort: 8081,951ContainerPort: 60,952},953},954err: "conflicting port mappings for host port 8081 (protocol tcp)",955},956{957name: "big port range with host port zero does not fit",958arg: []types.PortMapping{959{960HostPort: 0,961ContainerPort: 1,962Range: 65535,963},964},965err: "failed to find an open port to expose container port 1 with range 65535 on the host",966},967{968name: "big port range with host port zero does not fit",969arg: []types.PortMapping{970{971HostPort: 0,972ContainerPort: 80,973Range: 1,974},975{976HostPort: 0,977ContainerPort: 1000,978Range: 64535,979},980},981err: "failed to find an open port to expose container port 1000 with range 64535 on the host",982},983}984for _, tt := range tests {985tt := tt986t.Run(tt.name, func(t *testing.T) {987_, err := ParsePortMapping(tt.arg, nil)988assert.EqualError(t, err, tt.err, "error does not match")989})990}991}
992