summaryrefslogtreecommitdiff
path: root/swift/test/Ice/udp/AllTests.swift
blob: 305113372afafc8916a6320ee025e018eb8f059e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
//
// Copyright (c) ZeroC, Inc. All rights reserved.
//

import Dispatch
import Foundation
import Ice
import TestCommon

class PingReplyI: PingReply {
    var _replies: Int32 = 0
    var _lock = os_unfair_lock()
    var _semaphore = DispatchSemaphore(value: 0)

    func reset() {
        withLock(&_lock) {
            _replies = 0
        }
    }

    func reply(current _: Current) throws {
        withLock(&_lock) {
            _replies += 1
            _semaphore.signal()
        }
    }

    func waitReply(expectedReplies: Int, timeout: Int) -> Bool {
        let end = DispatchTime.now() + .milliseconds(timeout)
        while _replies < expectedReplies {
            let begin = DispatchTime.now()
            let delay = end.uptimeNanoseconds - begin.uptimeNanoseconds
            if delay > 0 {
                if _semaphore.wait(timeout: end) == .timedOut {
                    break
                }
            } else {
                break
            }
        }
        return _replies == expectedReplies
    }
}

public func allTests(_ helper: TestHelper) throws {
    func test(_ value: Bool, file: String = #file, line: Int = #line) throws {
        try helper.test(value, file: file, line: line)
    }

    let communicator = helper.communicator()
    communicator.getProperties().setProperty(key: "ReplyAdapter.Endpoints", value: "udp")
    let adapter = try communicator.createObjectAdapter("ReplyAdapter")
    var replyI = PingReplyI()
    var reply = try uncheckedCast(prx: adapter.addWithUUID(PingReplyDisp(replyI)),
                                  type: PingReplyPrx.self).ice_datagram()
    try adapter.activate()

    let output = helper.getWriter()

    output.write("testing udp... ")
    var base = try communicator.stringToProxy("test:\(helper.getTestEndpoint(num: 0, prot: "udp"))")!.ice_datagram()
    let obj = uncheckedCast(prx: base, type: TestIntfPrx.self)

    var ret = false
    for _ in 0 ..< 5 {
        replyI.reset()
        try obj.ping(reply)
        try obj.ping(reply)
        try obj.ping(reply)
        ret = replyI.waitReply(expectedReplies: 3, timeout: 2000)
        if ret {
            break // Success
        }

        // If the 3 datagrams were not received within the 2 seconds, we try again to
        // receive 3 new datagrams using a new object. We give up after 5 retries.
        replyI = PingReplyI()
        reply = try uncheckedCast(prx: adapter.addWithUUID(PingReplyDisp(replyI)),
                                  type: PingReplyPrx.self).ice_datagram()
    }
    try test(ret)

    if communicator.getProperties().getPropertyAsInt("Ice.Override.Compress") == 0 {
        //
        // Only run this test if compression is disabled, the test expect fixed message size
        // to be sent over the wire.
        //
        var seq: ByteSeq
        do {
            seq = ByteSeq(repeating: 0, count: 1024)
            while true {
                seq = ByteSeq(repeating: 0, count: seq.count * 2 + 10)
                replyI.reset()
                try obj.sendByteSeq(seq: seq, reply: reply)
                _ = replyI.waitReply(expectedReplies: 1, timeout: 10000)
            }
        } catch is Ice.DatagramLimitException {
            //
            // The server's Ice.UDP.RcvSize property is set to 16384, which means that DatagramLimitException
            // will be throw when try to send a packet bigger than that.
            //
            try test(seq.count > 16384)
        }
        try obj.ice_getConnection()!.close(.GracefullyWithWait)
        communicator.getProperties().setProperty(key: "Ice.UDP.SndSize", value: "64000")
        seq = ByteSeq(repeating: 0, count: 50000)
        do {
            replyI.reset()
            try obj.sendByteSeq(seq: seq, reply: reply)
            let b = replyI.waitReply(expectedReplies: 1, timeout: 500)
            //
            // The server's Ice.UDP.RcvSize property is set to 16384, which means this packet
            // should not be delivered.
            //
            try test(!b)
        } catch is Ice.DatagramLimitException {}
    }
    output.writeLine("ok")

    output.write("testing udp multicast... ")
    var endpoint = ""
    //
    // Use loopback to prevent other machines to answer.
    //
    if communicator.getProperties().getProperty("Ice.IPv6") == "1" {
        endpoint += "udp -h \"ff15::1:1\" --interface \"::1\""
    } else {
        endpoint += "udp -h 239.255.1.1 --interface 127.0.0.1"
    }
    endpoint += " -p "
    endpoint += "\(helper.getTestPort(num: 10))"
    base = try communicator.stringToProxy("test -d:\(endpoint)")!
    let objMcast = uncheckedCast(prx: base, type: TestIntfPrx.self)

    for _ in 0 ..< 5 {
        replyI.reset()
        do {
            try objMcast.ping(reply)
            ret = replyI.waitReply(expectedReplies: 5, timeout: 5000)
        } catch is Ice.SocketException where communicator.getProperties().getProperty("Ice.IPv6") == "1" {
            output.write("(not supported) ")
            ret = true
        }

        if ret {
            break
        }

        replyI = PingReplyI()
        reply = try uncheckedCast(prx: adapter.addWithUUID(PingReplyDisp(replyI)).ice_datagram(),
                                  type: PingReplyPrx.self)
    }

    if ret {
        output.writeLine("ok")
    } else {
        output.writeLine("failed(is a firewall enabled?)")
    }

    output.write("testing udp bi-dir connection... ")
    try obj.ice_getConnection()!.setAdapter(adapter)
    for _ in 0 ..< 5 {
        replyI.reset()
        try obj.pingBiDir(reply.ice_getIdentity())
        try obj.pingBiDir(reply.ice_getIdentity())
        try obj.pingBiDir(reply.ice_getIdentity())
        ret = replyI.waitReply(expectedReplies: 3, timeout: 2000)
        if ret {
            break // Success
        }
        replyI = PingReplyI()
        reply = try uncheckedCast(prx: adapter.addWithUUID(PingReplyDisp(replyI)),
                                  type: PingReplyPrx.self).ice_datagram()
    }
    try test(ret)
    output.writeLine("ok")

    //
    // Sending the replies back on the multicast UDP connection doesn't work for most
    // platform(it works for macOS Leopard but not Snow Leopard, doesn't work on SLES,
    // Windows...). For Windows, see UdpTransceiver constructor for the details. So
    // we don't run this test.
    //
    //         Console.Out.Write("testing udp bi-dir connection... ");
    //         nRetry = 5;
    //         while(nRetry-- > 0)
    //         {
    //             replyI.reset();
    //             objMcast.pingBiDir(reply.ice_getIdentity());
    //             ret = replyI.waitReply(5, 2000);
    //             if(ret)
    //             {
    //                 break; // Success
    //             }
    //             replyI = new PingReplyI();
    //             reply =(PingReplyPrx)PingReplyPrxHelper.uncheckedCast(adapter.addWithUUID(replyI)).ice_datagram();
    //         }

    //         if(!ret)
    //         {
    //             Console.Out.WriteLine("failed(is a firewall enabled?)");
    //         }
    //         else
    //         {
    //             Console.Out.WriteLine("ok");
    //         }
}