diff --git a/src/main/groovy/com/blogspot/przybyszd/mockserver/ContextExecutor.groovy b/src/main/groovy/com/blogspot/przybyszd/mockserver/ContextExecutor.groovy new file mode 100644 index 0000000..a83efe1 --- /dev/null +++ b/src/main/groovy/com/blogspot/przybyszd/mockserver/ContextExecutor.groovy @@ -0,0 +1,44 @@ +package com.blogspot.przybyszd.mockserver + +import com.sun.net.httpserver.HttpExchange +import groovy.util.slurpersupport.GPathResult + +import java.util.concurrent.CopyOnWriteArrayList + +class ContextExecutor { + private final HttpServerWraper httpServerWraper + private final String path + private final List mocks + + ContextExecutor(HttpServerWraper httpServerWraper, String path, Mock initialMock) { + this.httpServerWraper = httpServerWraper + this.path = path + this.mocks = new CopyOnWriteArrayList<>([initialMock]) + httpServerWraper.createContext(path,{ + HttpExchange ex -> + ex.sendResponseHeaders(200, 0) + String input = ex.requestBody.text + println "Mock received input" + GPathResult xml = new XmlSlurper().parseText(input) + for (Mock mock : mocks){ + if(mock.predicate(xml)){ + println "Mock ${mock.name} invoked" + ++mock.counter + ex.responseBody << mock.responseOk(xml) + ex.responseBody.close() + return + } + } + ex.responseBody << "" + ex.responseBody.close() + }) + } + + int removeMock(String name) { + Mock mock = mocks.find {it.name == name} + if(mock){ + mocks.remove(mock) + } + return mock.counter + } +} diff --git a/src/main/groovy/com/blogspot/przybyszd/mockserver/HttpMockServer.groovy b/src/main/groovy/com/blogspot/przybyszd/mockserver/HttpMockServer.groovy index 2b1cbf8..205fdd6 100644 --- a/src/main/groovy/com/blogspot/przybyszd/mockserver/HttpMockServer.groovy +++ b/src/main/groovy/com/blogspot/przybyszd/mockserver/HttpMockServer.groovy @@ -1,20 +1,16 @@ package com.blogspot.przybyszd.mockserver import com.sun.net.httpserver.HttpExchange -import com.sun.net.httpserver.HttpHandler -import com.sun.net.httpserver.HttpServer -import groovy.transform.EqualsAndHashCode import groovy.util.slurpersupport.GPathResult import java.util.concurrent.CopyOnWriteArrayList import java.util.concurrent.CopyOnWriteArraySet -import java.util.concurrent.Executors class HttpMockServer { - HttpServerWraper httpServerWraper - List childServers = new CopyOnWriteArrayList<>() - Set mockNames = new CopyOnWriteArraySet<>() + private final HttpServerWraper httpServerWraper + private final List childServers = new CopyOnWriteArrayList<>() + private final Set mockNames = new CopyOnWriteArraySet<>() HttpMockServer(int port = 9999){ httpServerWraper= new HttpServerWraper(port) @@ -63,9 +59,10 @@ class HttpMockServer { if (! (name in mockNames)) { throw new RuntimeException('mock not registered') } - childServers.each {it.removeMock(name)} + println "Removing $name" + int used = childServers.inject(0) { int res, HttpServerWraper server-> server.removeMock(name) + res} mockNames.remove(name) - ex.responseBody << '' + ex.responseBody << "$used" ex.responseBody.close() } @@ -78,107 +75,4 @@ class HttpMockServer { childServers.each {it.stop()} httpServerWraper.stop() } - - private static final class HttpServerWraper{ - final HttpServer httpServer - final int port - - List executors = [] - - HttpServerWraper(int port){ - this.port = port - InetSocketAddress addr = new InetSocketAddress(Inet4Address.getByName("0.0.0.0"), port) - httpServer = HttpServer.create(addr, 0) - httpServer.executor = Executors.newCachedThreadPool() - println "Http server statrting on port $port..." - httpServer.start() - println 'Http server is started' - } - - void createContext(String context, HttpHandler handler){ - httpServer.createContext(context, handler) - } - - void addMock(String path, Mock mock){ - ContextExecutor executor = executors.find {it.path == path} - if(executor){ - executor.mocks << mock - }else { - executors << new ContextExecutor(this, path, mock) - } - } - - void stop(){ - executors.each {httpServer.removeContext(it.path)} - httpServer.stop(0) - } - - void removeMock(String name) { - executors.each {it.removeMock(name)} - } - } - - private static final class ContextExecutor{ - final HttpServerWraper httpServerWraper - final String path - List mocks - - ContextExecutor(HttpServerWraper httpServerWraper, String path, Mock initialMock) { - this.httpServerWraper = httpServerWraper - this.path = path - this.mocks = new CopyOnWriteArrayList<>([initialMock]) - httpServerWraper.createContext(path,{ - HttpExchange ex -> - ex.sendResponseHeaders(200, 0) - String input = ex.requestBody.text - println "Mock received input" - GPathResult xml = new XmlSlurper().parseText(input) - for (Mock mock : mocks){ - if(mock.predicate(xml)){ - ex.responseBody << mock.responseOk(xml) - ex.responseBody.close() - return - } - } - ex.responseBody << "" - ex.responseBody.close() - }) - } - - void removeMock(String name) { - Mock mock = mocks.find {it.name == name} - if(mock){ - mocks.remove(mock) - } - } - } - - @EqualsAndHashCode - private static final class Mock { - final String name - final Closure predicate - final Closure responseOk - //TODO add http method - //TODO add is soap method - - Mock(String name, Closure predicate, Closure responseOk) { - this.name = name - this.predicate = predicate - this.responseOk = responseOk - } - } - - static void main(String [] args) { - HttpMockServer httpMockServer = new HttpMockServer() - - Runtime.runtime.addShutdownHook(new Thread({ - println 'Http server is stopping...' - httpMockServer.stop() - println 'Http server is stopped' - } as Runnable)) - - while(true){ - Thread.sleep(10000) - } - } } diff --git a/src/main/groovy/com/blogspot/przybyszd/mockserver/HttpServerWraper.groovy b/src/main/groovy/com/blogspot/przybyszd/mockserver/HttpServerWraper.groovy new file mode 100644 index 0000000..bf32aca --- /dev/null +++ b/src/main/groovy/com/blogspot/przybyszd/mockserver/HttpServerWraper.groovy @@ -0,0 +1,45 @@ +package com.blogspot.przybyszd.mockserver + +import com.sun.net.httpserver.HttpHandler +import com.sun.net.httpserver.HttpServer + +import java.util.concurrent.Executors + +class HttpServerWraper { + private final HttpServer httpServer + private final int port + + private List executors = [] + + HttpServerWraper(int port) { + this.port = port + InetSocketAddress addr = new InetSocketAddress(Inet4Address.getByName("0.0.0.0"), port) + httpServer = HttpServer.create(addr, 0) + httpServer.executor = Executors.newCachedThreadPool() + println "Http server statrting on port $port..." + httpServer.start() + println 'Http server is started' + } + + void createContext(String context, HttpHandler handler) { + httpServer.createContext(context, handler) + } + + void addMock(String path, Mock mock) { + ContextExecutor executor = executors.find { it.path == path } + if (executor) { + executor.mocks << mock + } else { + executors << new ContextExecutor(this, path, mock) + } + } + + void stop() { + executors.each { httpServer.removeContext(it.path) } + httpServer.stop(0) + } + + int removeMock(String name) { + executors.inject(0) { int res, ContextExecutor e -> e.removeMock(name) + res} + } +} diff --git a/src/main/groovy/com/blogspot/przybyszd/mockserver/Main.groovy b/src/main/groovy/com/blogspot/przybyszd/mockserver/Main.groovy new file mode 100644 index 0000000..66f9542 --- /dev/null +++ b/src/main/groovy/com/blogspot/przybyszd/mockserver/Main.groovy @@ -0,0 +1,17 @@ +package com.blogspot.przybyszd.mockserver + +class Main { + static void main(String [] args) { + HttpMockServer httpMockServer = new HttpMockServer() + + Runtime.runtime.addShutdownHook(new Thread({ + println 'Http server is stopping...' + httpMockServer.stop() + println 'Http server is stopped' + } as Runnable)) + + while(true){ + Thread.sleep(10000) + } + } +} diff --git a/src/main/groovy/com/blogspot/przybyszd/mockserver/Mock.groovy b/src/main/groovy/com/blogspot/przybyszd/mockserver/Mock.groovy new file mode 100644 index 0000000..4f6e743 --- /dev/null +++ b/src/main/groovy/com/blogspot/przybyszd/mockserver/Mock.groovy @@ -0,0 +1,19 @@ +package com.blogspot.przybyszd.mockserver + +import groovy.transform.EqualsAndHashCode + +@EqualsAndHashCode(excludes = ["counter"]) +class Mock { + final String name + final Closure predicate + final Closure responseOk + //TODO add http method + //TODO add is soap method + int counter = 0 + + Mock(String name, Closure predicate, Closure responseOk) { + this.name = name + this.predicate = predicate + this.responseOk = responseOk + } +}