Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reduce test pollution with spec.name and requires in http-client tests #10084

Merged
merged 2 commits into from
Nov 8, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,18 +1,3 @@
/*
* Copyright 2017-2019 original authors
*
* 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 io.micronaut.http.client

import io.micronaut.context.ApplicationContext
Expand All @@ -24,10 +9,20 @@ import io.micronaut.http.annotation.Get
import io.micronaut.runtime.server.EmbeddedServer
import org.reactivestreams.Publisher
import reactor.core.publisher.Flux
import spock.lang.AutoCleanup
import spock.lang.Shared
import spock.lang.Specification

class BasicAuthSpec extends Specification {

@Shared
@AutoCleanup
EmbeddedServer server = ApplicationContext.run(EmbeddedServer, [
'spec.name': 'BasicAuthSpec'
])

HttpClient httpClient = server.applicationContext.createBean(HttpClient, new URL("http://sherlock:password@localhost:${server.port}"))

def "basicAuth() sets Authorization Header with Basic base64(username:password)"() {
when:
// tag::basicAuth[]
Expand All @@ -40,23 +35,11 @@ class BasicAuthSpec extends Specification {
}

void "test user in absolute URL"() {
given:
EmbeddedServer server = ApplicationContext.run(EmbeddedServer, [
'spec.name': 'BasicAuthSpec'
])
ApplicationContext ctx = server.applicationContext
HttpClient httpClient = ctx.createBean(HttpClient, new URL("http://sherlock:password@localhost:${server.port}"))

when:
String resp = httpClient.toBlocking().retrieve("/basicauth")

then:
resp == "sherlock:password"

cleanup:
httpClient.close()
ctx.close()
server.close()
}

@Requires(property = 'spec.name', value = 'BasicAuthSpec')
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,54 +3,51 @@ package io.micronaut.http.client
import io.micronaut.context.ApplicationContext
import io.micronaut.http.client.exceptions.HttpClientException
import io.micronaut.http.netty.channel.EventLoopGroupRegistry
import io.netty.channel.EventLoopGroup
import spock.lang.AutoCleanup
import spock.lang.Shared
import spock.lang.Specification

import java.util.concurrent.ExecutionException

class BlockingDeadlockSpec extends Specification {
def 'blocking on the same event loop should fail: connection already established'() {
given:
def ctx = ApplicationContext.run([
'micronaut.netty.event-loops.default.num-threads': 1
])
def group = ctx.getBean(EventLoopGroupRegistry).getDefaultEventLoopGroup()
def client = ctx.createBean(HttpClient, 'https://micronaut.io').toBlocking()

@Shared
@AutoCleanup
ApplicationContext ctx = ApplicationContext.run([
'micronaut.netty.event-loops.default.num-threads': 1
])

@Shared
EventLoopGroup group = ctx.getBean(EventLoopGroupRegistry).getDefaultEventLoopGroup()

@Shared
@AutoCleanup
BlockingHttpClient client = ctx.createBean(HttpClient, 'https://micronaut.io').toBlocking()

def 'blocking on the same event loop should fail: connection already established'() {
when:
// establish pool connection
client.exchange('/')
group.submit(() -> {
client.exchange('/')
}).get()

then:
def e = thrown ExecutionException
e.cause instanceof HttpClientException
e.cause.message.contains("deadlock")

cleanup:
client.close()
group.shutdownGracefully()
}

def 'blocking on the same event loop should fail: new connection'() {
given:
def ctx = ApplicationContext.run([
'micronaut.netty.event-loops.default.num-threads': 1
])
def group = ctx.getBean(EventLoopGroupRegistry).getDefaultEventLoopGroup()
def client = ctx.createBean(HttpClient, 'https://micronaut.io').toBlocking()

when:
group.submit(() -> {
client.exchange('/')
}).get()

then:
def e = thrown ExecutionException
e.cause instanceof HttpClientException
e.cause.message.contains("deadlock")

cleanup:
client.close()
group.shutdownGracefully()
}
}
Original file line number Diff line number Diff line change
@@ -1,18 +1,3 @@
/*
* Copyright 2017-2019 original authors
*
* 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 io.micronaut.http.client

import io.micronaut.context.ApplicationContext
Expand All @@ -27,151 +12,115 @@ import io.micronaut.http.annotation.*
import io.micronaut.http.client.annotation.Client
import io.micronaut.http.client.exceptions.HttpClientResponseException
import io.micronaut.runtime.server.EmbeddedServer
import spock.lang.AutoCleanup
import spock.lang.Specification

class ClientIntroductionAdviceSpec extends Specification {

@AutoCleanup
EmbeddedServer server = ApplicationContext.run(EmbeddedServer, [
'spec.name': 'ClientIntroductionAdviceSpec',
])

void "test implement HTTP client"() {
given:
EmbeddedServer embeddedServer = ApplicationContext.run(EmbeddedServer, ['spec.name': 'ClientIntroductionAdviceSpec'])
MyClient myService = embeddedServer.applicationContext.getBean(MyClient)
MyClient myService = server.applicationContext.getBean(MyClient)

expect:
myService.index() == 'success'

cleanup:
embeddedServer.close()
}

void "service id appears in exceptions"() {
given:
EmbeddedServer embeddedServer = ApplicationContext.run(EmbeddedServer, ['spec.name': 'ClientIntroductionAdviceSpec'])
embeddedServer.applicationContext.registerSingleton(new TestServiceInstanceList(embeddedServer.getURI()))

PolicyClient myService = embeddedServer.applicationContext.getBean(PolicyClient)
server.applicationContext.registerSingleton(new TestServiceInstanceList(server.getURI()))
PolicyClient myService = server.applicationContext.getBean(PolicyClient)

when:
myService.failure()

then:
def e = thrown(HttpClientResponseException)
e.serviceId == 'test-service'
e.message == "Client 'test-service': Bad Request"

cleanup:
embeddedServer.close()
}

void "test multiple clients with the same id and different paths"() {
given:
EmbeddedServer server = ApplicationContext.run(EmbeddedServer, ['spec.name': 'ClientIntroductionAdviceSpec'])
server.applicationContext.registerSingleton(new TestServiceInstanceList(server.getURI()))

expect:
server.applicationContext.getBean(PolicyClient).index() == 'policy'
server.applicationContext.getBean(OfferClient).index() == 'offer'

cleanup:
server.close()
}

void "test a client with a body and header"() {
given:
EmbeddedServer server = ApplicationContext.run(EmbeddedServer, ['spec.name': 'ClientIntroductionAdviceSpec'])
server.applicationContext.registerSingleton(new TestServiceInstanceList(server.getURI()))

when:
OfferClient client = server.applicationContext.getBean(OfferClient)

then:
client.post('abc', 'bar') == 'abc header=bar'

cleanup:
server.close()
}

void "test a client that auto encodes basic auth header"() {
given:
EmbeddedServer server = ApplicationContext.run(EmbeddedServer, ['spec.name': 'ClientIntroductionAdviceSpec'])
server.applicationContext.registerSingleton(new TestServiceInstanceList(server.getURI()))

when:
ApplicationContext ctx = ApplicationContext.run(['spec.name': 'ClientIntroductionAdviceSpec', 'server-port': server.port])
BasicAuthHeaderAutoEncodingClient client = server.applicationContext.getBean(BasicAuthHeaderAutoEncodingClient)

then:
client.post('abc', new BasicAuth("username", "password")) == 'abc basic-auth-header=Basic dXNlcm5hbWU6cGFzc3dvcmQ='

cleanup:
server.close()
}

void "test non body params have preference for uri templates"() {
given:
EmbeddedServer server = ApplicationContext.run(EmbeddedServer, ['spec.name': 'ClientIntroductionAdviceSpec'])

when:
LocalOfferClient client = server.applicationContext.getBean(LocalOfferClient)

then:
client.putTest("abc", new MyObject(code: "def")) == "abc"

cleanup:
server.close()
}

void "test basic auth"() {
given:
EmbeddedServer server = ApplicationContext.run(EmbeddedServer, ['spec.name': 'ClientIntroductionAdviceSpec'])
ApplicationContext ctx = ApplicationContext.run(['spec.name': 'ClientIntroductionAdviceSpec', 'server-port': server.port])

when:
ApplicationContext ctx = ApplicationContext.run(['spec.name': 'ClientIntroductionAdviceSpec', 'server-port': server.port])
BasicAuthClient client = ctx.getBean(BasicAuthClient)

then:
client.get() == 'config:secret'

cleanup:
ctx.close()
server.close()
}

void "test execution of a default method"() {
given:
EmbeddedServer server = ApplicationContext.run(EmbeddedServer, ['spec.name': 'ClientIntroductionAdviceSpec'])
DefaultMethodClient myService = server.applicationContext.getBean(DefaultMethodClient)

expect:
myService.defaultMethod() == 'success from default method mutated'

cleanup:
server.close()
}

void "test execution of a default method 2"() {
given:
EmbeddedServer server = ApplicationContext.run(EmbeddedServer, ['spec.name': 'ClientIntroductionAdviceSpec'])
DefaultMethodClient2 myService = server.applicationContext.getBean(DefaultMethodClient2)

expect:
myService.index("ZZZ") == 'success ZZZ XYZ from default method'
myService.defaultMethod() == 'success from default method mutated'
myService.defaultMethod2("ABC") == 'success ABC XYZ from default method 2 mutated'

cleanup:
server.close()
}

void "test execution of a default method 3"() {
given:
EmbeddedServer server = ApplicationContext.run(EmbeddedServer, ['spec.name': 'ClientIntroductionAdviceSpec'])
DefaultMethodClient3 myService = server.applicationContext.getBean(DefaultMethodClient3)

expect:
myService.index("ZZZ") == 'success ZZZ XYZ from default method'
myService.defaultMethod() == 'success from default method mutated'
myService.defaultMethod2("ABC") == 'success ABC XYZ from default method 2 mutated'

cleanup:
server.close()
}

@Requires(property = 'spec.name', value = 'ClientIntroductionAdviceSpec')
Expand Down
Loading