1package dns 2 3import ( 4 "fmt" 5 "testing" 6) 7 8func TestRequestTruncateAnswer(t *testing.T) { 9 m := new(Msg) 10 m.SetQuestion("large.example.com.", TypeSRV) 11 12 reply := new(Msg) 13 reply.SetReply(m) 14 for i := 1; i < 200; i++ { 15 reply.Answer = append(reply.Answer, testRR( 16 fmt.Sprintf("large.example.com. 10 IN SRV 0 0 80 10-0-0-%d.default.pod.k8s.example.com.", i))) 17 } 18 19 reply.Truncate(MinMsgSize) 20 if want, got := MinMsgSize, reply.Len(); want < got { 21 t.Errorf("message length should be bellow %d bytes, got %d bytes", want, got) 22 } 23 if !reply.Truncated { 24 t.Errorf("truncated bit should be set") 25 } 26} 27 28func TestRequestTruncateExtra(t *testing.T) { 29 m := new(Msg) 30 m.SetQuestion("large.example.com.", TypeSRV) 31 32 reply := new(Msg) 33 reply.SetReply(m) 34 for i := 1; i < 200; i++ { 35 reply.Extra = append(reply.Extra, testRR( 36 fmt.Sprintf("large.example.com. 10 IN SRV 0 0 80 10-0-0-%d.default.pod.k8s.example.com.", i))) 37 } 38 39 reply.Truncate(MinMsgSize) 40 if want, got := MinMsgSize, reply.Len(); want < got { 41 t.Errorf("message length should be bellow %d bytes, got %d bytes", want, got) 42 } 43 if !reply.Truncated { 44 t.Errorf("truncated bit should be set") 45 } 46} 47 48func TestRequestTruncateExtraEdns0(t *testing.T) { 49 const size = 4096 50 51 m := new(Msg) 52 m.SetQuestion("large.example.com.", TypeSRV) 53 m.SetEdns0(size, true) 54 55 reply := new(Msg) 56 reply.SetReply(m) 57 for i := 1; i < 200; i++ { 58 reply.Extra = append(reply.Extra, testRR( 59 fmt.Sprintf("large.example.com. 10 IN SRV 0 0 80 10-0-0-%d.default.pod.k8s.example.com.", i))) 60 } 61 reply.SetEdns0(size, true) 62 63 reply.Truncate(size) 64 if want, got := size, reply.Len(); want < got { 65 t.Errorf("message length should be bellow %d bytes, got %d bytes", want, got) 66 } 67 if !reply.Truncated { 68 t.Errorf("truncated bit should be set") 69 } 70 opt := reply.Extra[len(reply.Extra)-1] 71 if opt.Header().Rrtype != TypeOPT { 72 t.Errorf("expected last RR to be OPT") 73 } 74} 75 76func TestRequestTruncateExtraRegression(t *testing.T) { 77 const size = 2048 78 79 m := new(Msg) 80 m.SetQuestion("large.example.com.", TypeSRV) 81 m.SetEdns0(size, true) 82 83 reply := new(Msg) 84 reply.SetReply(m) 85 for i := 1; i < 33; i++ { 86 reply.Answer = append(reply.Answer, testRR( 87 fmt.Sprintf("large.example.com. 10 IN SRV 0 0 80 10-0-0-%d.default.pod.k8s.example.com.", i))) 88 } 89 for i := 1; i < 33; i++ { 90 reply.Extra = append(reply.Extra, testRR( 91 fmt.Sprintf("10-0-0-%d.default.pod.k8s.example.com. 10 IN A 10.0.0.%d", i, i))) 92 } 93 reply.SetEdns0(size, true) 94 95 reply.Truncate(size) 96 if want, got := size, reply.Len(); want < got { 97 t.Errorf("message length should be bellow %d bytes, got %d bytes", want, got) 98 } 99 if !reply.Truncated { 100 t.Errorf("truncated bit should be set") 101 } 102 opt := reply.Extra[len(reply.Extra)-1] 103 if opt.Header().Rrtype != TypeOPT { 104 t.Errorf("expected last RR to be OPT") 105 } 106} 107 108func TestTruncation(t *testing.T) { 109 reply := new(Msg) 110 111 for i := 0; i < 61; i++ { 112 reply.Answer = append(reply.Answer, testRR(fmt.Sprintf("http.service.tcp.srv.k8s.example.org. 5 IN SRV 0 0 80 10-144-230-%d.default.pod.k8s.example.org.", i))) 113 } 114 115 for i := 0; i < 5; i++ { 116 reply.Extra = append(reply.Extra, testRR(fmt.Sprintf("ip-10-10-52-5%d.subdomain.example.org. 5 IN A 10.10.52.5%d", i, i))) 117 } 118 119 for i := 0; i < 5; i++ { 120 reply.Ns = append(reply.Ns, testRR(fmt.Sprintf("srv.subdomain.example.org. 5 IN NS ip-10-10-33-6%d.subdomain.example.org.", i))) 121 } 122 123 for bufsize := 1024; bufsize <= 4096; bufsize += 12 { 124 m := new(Msg) 125 m.SetQuestion("http.service.tcp.srv.k8s.example.org.", TypeSRV) 126 m.SetEdns0(uint16(bufsize), true) 127 128 copy := reply.Copy() 129 copy.SetReply(m) 130 131 copy.Truncate(bufsize) 132 if want, got := bufsize, copy.Len(); want < got { 133 t.Errorf("message length should be bellow %d bytes, got %d bytes", want, got) 134 } 135 } 136} 137 138func TestRequestTruncateAnswerExact(t *testing.T) { 139 const size = 867 // Bit fiddly, but this hits the rl == size break clause in Truncate, 52 RRs should remain. 140 141 m := new(Msg) 142 m.SetQuestion("large.example.com.", TypeSRV) 143 m.SetEdns0(size, false) 144 145 reply := new(Msg) 146 reply.SetReply(m) 147 for i := 1; i < 200; i++ { 148 reply.Answer = append(reply.Answer, testRR(fmt.Sprintf("large.example.com. 10 IN A 127.0.0.%d", i))) 149 } 150 151 reply.Truncate(size) 152 if want, got := size, reply.Len(); want < got { 153 t.Errorf("message length should be bellow %d bytes, got %d bytes", want, got) 154 } 155 if expected := 52; len(reply.Answer) != expected { 156 t.Errorf("wrong number of answers; expected %d, got %d", expected, len(reply.Answer)) 157 } 158} 159 160func BenchmarkMsgTruncate(b *testing.B) { 161 const size = 2048 162 163 m := new(Msg) 164 m.SetQuestion("example.com.", TypeA) 165 m.SetEdns0(size, true) 166 167 reply := new(Msg) 168 reply.SetReply(m) 169 for i := 1; i < 33; i++ { 170 reply.Answer = append(reply.Answer, testRR( 171 fmt.Sprintf("large.example.com. 10 IN SRV 0 0 80 10-0-0-%d.default.pod.k8s.example.com.", i))) 172 } 173 for i := 1; i < 33; i++ { 174 reply.Extra = append(reply.Extra, testRR( 175 fmt.Sprintf("10-0-0-%d.default.pod.k8s.example.com. 10 IN A 10.0.0.%d", i, i))) 176 } 177 178 b.ResetTimer() 179 180 for i := 0; i < b.N; i++ { 181 b.StopTimer() 182 copy := reply.Copy() 183 b.StartTimer() 184 185 copy.Truncate(size) 186 } 187} 188