Skip to content
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
9 changes: 9 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,10 @@
__pycache__
.pytest_cache
node_modules
.venv
# rust build artifacts
target
# typescript build output from npm test
build
# make test output
test-results.log
6 changes: 4 additions & 2 deletions go/hello/function.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package function

import (
"encoding/json"
"fmt"
"net/http"
)
Expand All @@ -17,6 +18,7 @@ func New() *MyFunction {

// Handle an HTTP Request.
func (f *MyFunction) Handle(w http.ResponseWriter, r *http.Request) {
fmt.Print("Received a request\n") //printed on server
fmt.Fprint(w, "Hello Go World!") //send to client
fmt.Print("Received a request\n") //printed on server
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(map[string]string{"message": "Hello Go World!"})
}
13 changes: 13 additions & 0 deletions go/hello/function_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package function

import (
"encoding/json"
"net/http"
"net/http/httptest"
"testing"
Expand All @@ -22,4 +23,16 @@ func TestHandle(t *testing.T) {
if res.StatusCode != 200 {
t.Fatalf("unexpected response code: %v", res.StatusCode)
}

if ct := w.Header().Get("Content-Type"); ct != "application/json" {
t.Fatalf("unexpected content type: %v", ct)
}

var resp map[string]string
if err := json.NewDecoder(w.Body).Decode(&resp); err != nil {
t.Fatalf("failed to decode response: %v", err)
}
if resp["message"] != "Hello Go World!" {
t.Fatalf("unexpected message: %v", resp["message"])
}
}
4 changes: 2 additions & 2 deletions node/hello/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@ const handle = async (context, body) => {
console.log("Recieved request!") // printed on server
// If the request is an HTTP GET/POST
if (context.method === 'POST' || context.method === 'GET'){
return { statusMessage: "Hello Node World!"} // send to client
return { body: { message: "Hello Node World!" } } // send to client
} else {
return { statusCode: 405, statusMessage: 'Method not allowed' };
return { statusCode: 405, body: 'Method not allowed' };
}
}

Expand Down
8 changes: 3 additions & 5 deletions node/hello/test/integration.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,12 @@ test('Integration: handles an HTTP GET', t => {
start(func).then(server => {
t.plan(2);
request(server)
.get('/?name=tiger')
.get('/')
.expect(200)
.expect('Content-Type', /json/)
.end((err, res) => {
t.error(err, 'No error');
t.deepEqual(res.body, { query: { name: 'tiger' } });
t.deepEqual(res.body, { message: 'Hello Node World!' });
t.end();
server.close();
});
Expand All @@ -32,12 +32,11 @@ test('Integration: handles an HTTP POST', t => {
t.plan(2);
request(server)
.post('/')
.send({ name: 'tiger' })
.expect(200)
.expect('Content-Type', /json/)
.end((err, res) => {
t.error(err, 'No error');
t.deepEqual(res.body, { name: 'tiger' });
t.deepEqual(res.body, { message: 'Hello Node World!' });
t.end();
server.close();
});
Expand All @@ -49,7 +48,6 @@ test('Integration: responds with error code if neither GET or POST', t => {
t.plan(1);
request(server)
.put('/')
.send({ name: 'tiger' })
.expect(200)
.expect('Content-Type', /json/)
.end((err, res) => {
Expand Down
13 changes: 5 additions & 8 deletions node/hello/test/unit.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,24 +7,21 @@ const fixture = { log: { info: console.log } };

test('Unit: handles an HTTP GET', async t => {
t.plan(1);
// Invoke the function, which should complete without error.
const result = await func({ ...fixture, method: 'GET', query: { name: 'tiger' } });
t.deepEqual(result, { query: { name: 'tiger' } });
const result = await func({ ...fixture, method: 'GET' });
t.deepEqual(result, { body: { message: 'Hello Node World!' } });
t.end();
});

test('Unit: handles an HTTP POST', async t => {
t.plan(1);
const body = { name: 'tiger' };
// Invoke the function, which should complete without error.
const result = await func({ ...fixture, method: 'POST', body }, body);
t.deepEqual(result, { body });
const result = await func({ ...fixture, method: 'POST' });
t.deepEqual(result, { body: { message: 'Hello Node World!' } });
t.end();
});

test('Unit: responds with error code if neither GET or POST', async t => {
t.plan(1);
const result = await func(fixture);
t.deepEqual(result, { statusCode: 405, statusMessage: 'Method not allowed' });
t.deepEqual(result, { statusCode: 405, body: 'Method not allowed' });
t.end();
});
68 changes: 47 additions & 21 deletions python/echo/tests/test_func.py
Original file line number Diff line number Diff line change
@@ -1,38 +1,64 @@
"""
An example set of unit tests which confirm that the main handler (the
callable function) returns 200 OK for a simple HTTP GET.
Unit tests for the echo function. Verifies that GET echoes the query string
and POST echoes the request body.
"""
import pytest
from function import new

@pytest.mark.asyncio
async def test_get_echoes_query_string():
f = new()

sent_body = None

async def send(message):
nonlocal sent_body
# capture the body (second send() call)
if message.get('type') == 'http.response.body':
sent_body = message.get('body')

scope = {'method': 'GET', 'query_string': b'message=hello'}
await f.handle(scope, None, send)

assert sent_body == b'message=hello', f"Unexpected body: {sent_body}"


@pytest.mark.asyncio
async def test_function_handle():
f = new() # Instantiate Function to Test
async def test_post_echoes_request_body():
f = new()

sent_ok = False
sent_headers = False
sent_body = False
sent_body = None

# Mock Send
async def send(message):
nonlocal sent_ok
nonlocal sent_headers
nonlocal sent_body
# capture the body (second send() call)
if message.get('type') == 'http.response.body':
sent_body = message.get('body')

request_body = b'{"message":"Hello World"}'

async def receive():
return {'body': request_body, 'more_body': False}

if message.get('status') == 200:
sent_ok = True
scope = {'method': 'POST'}
await f.handle(scope, receive, send)

if message.get('type') == 'http.response.start':
sent_headers = True
assert sent_body == request_body, f"Unexpected body: {sent_body}"


@pytest.mark.asyncio
async def test_get_empty_query_string():
f = new()

sent_body = None

async def send(message):
nonlocal sent_body
# capture the body (second send() call)
if message.get('type') == 'http.response.body':
sent_body = True
sent_body = message.get('body')

# Invoke the Function
await f.handle({}, {}, send)
scope = {'method': 'GET'}
await f.handle(scope, None, send)

# Assert send was called
assert sent_ok, "Function did not send a 200 OK"
assert sent_headers, "Function did not send headers"
assert sent_body, "Function did not send a body"
assert sent_body == b'', f"Unexpected body: {sent_body}"
6 changes: 2 additions & 4 deletions python/hello/function/func.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ def new():
"""
return Function()


class Function:
def __init__(self):
""" The init method is an optional method where initialization can be
Expand All @@ -22,17 +21,16 @@ async def handle(self, scope, receive, send):

logging.info("OK: Request Received")

# echo the request to the calling client
await send({
'type': 'http.response.start',
'status': 200,
'headers': [
[b'content-type', b'text/plain'],
[b'content-type', b'application/json'],
],
})
await send({
'type': 'http.response.body',
'body': 'Hello Python World!'.encode(),
'body': '{"message":"Hello Python World!"}'.encode(),
})

def start(self, cfg):
Expand Down
7 changes: 3 additions & 4 deletions python/hello/tests/test_func.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,13 @@
import pytest
from function import new


@pytest.mark.asyncio
async def test_function_handle():
f = new() # Instantiate Function to Test

sent_ok = False
sent_headers = False
sent_body = False
sent_body = None

# Mock Send
async def send(message):
Expand All @@ -27,12 +26,12 @@ async def send(message):
sent_headers = True

if message.get('type') == 'http.response.body':
sent_body = True
sent_body = message.get('body')

# Invoke the Function
await f.handle({}, {}, send)

# Assert send was called
assert sent_ok, "Function did not send a 200 OK"
assert sent_headers, "Function did not send headers"
assert sent_body, "Function did not send a body"
assert sent_body == b'{"message":"Hello Python World!"}', f"Unexpected body: {sent_body}"
8 changes: 5 additions & 3 deletions rust/hello/src/handler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@ use log::info;
pub async fn index(req: HttpRequest, config: Data<HandlerConfig>) -> HttpResponse {
info!("{:#?}", req);
if req.method() == Method::GET || req.method() == Method::POST{
HttpResponse::Ok().body(format!("{}\n",config.response))
HttpResponse::Ok()
.content_type("application/json")
.body(format!("{{\"message\":\"{}\"}}", config.response))
} else {
HttpResponse::Ok().body("Unknown method\n")
}
Expand All @@ -27,7 +29,7 @@ mod tests {
let resp = index(req, config()).await;
assert_eq!(resp.status(), http::StatusCode::OK);
assert_eq!(
&Bytes::from("Hello Rust World!\n"),
&Bytes::from("{\"message\":\"Hello Rust World!\"}"),
to_bytes(resp.into_body()).await.unwrap().as_ref()
);
}
Expand All @@ -38,7 +40,7 @@ mod tests {
let resp = index(req, config()).await;
assert!(resp.status().is_success());
assert_eq!(
&Bytes::from("Hello Rust World!\n"),
&Bytes::from("{\"message\":\"Hello Rust World!\"}"),
to_bytes(resp.into_body()).await.unwrap().as_ref()
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,6 @@ public static void main(String[] args) {

@Bean
public Function<Message<String>, String> echo() {
return inputMessage -> "Hello Springboot World!";
return inputMessage -> "{\"message\":\"Hello Springboot World!\"}";
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,6 @@ public void testEcho() throws Exception {
ResponseEntity<String> response = this.rest.exchange(request,String.class);
// assert status code and return value
assertThat(response.getStatusCode().value(), equalTo(200));
assertThat(response.getBody(), containsString("Hello Springboot World!"));
assertThat(response.getBody(), containsString("{\"message\":\"Hello Springboot World!\"}"));
}
}
Loading