Skip to content

Commit 33cce77

Browse files
peterborkutiborkupe
andauthored
Fix s3 tests for s3 examples (awslabs#675)
* upgrade basic-s3-thumbnail example + refactor test I noticed that I am testing thumbnailer module when I compared the generated thumbnail with a stored one. This can lead test failures. So I mocked the thumbnail generation. * refactor test for basic-s3-object-lambda example --------- Co-authored-by: borkupe <[email protected]>
1 parent 2b7d161 commit 33cce77

File tree

7 files changed

+71
-67
lines changed

7 files changed

+71
-67
lines changed

examples/basic-s3-object-lambda-thumbnail/src/main.rs

Lines changed: 24 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
1-
use std::{error, io::Cursor};
1+
use std::error;
22

33
use aws_lambda_events::s3::object_lambda::{GetObjectContext, S3ObjectLambdaEvent};
44
use aws_sdk_s3::Client as S3Client;
55
use lambda_runtime::{run, service_fn, Error, LambdaEvent};
66
use s3::{GetFile, SendFile};
7-
use thumbnailer::{create_thumbnails, ThumbnailSize};
87

98
mod s3;
109

@@ -35,28 +34,21 @@ pub(crate) async fn function_handler<T: SendFile + GetFile>(
3534
let thumbnail = get_thumbnail(image, size);
3635
tracing::info!("thumbnail created. Length: {}", thumbnail.len());
3736

38-
// It sends the thumbnail back to the user
39-
4037
client.send_file(route, token, thumbnail).await
41-
42-
/*
43-
match client.send_file(route, token, thumbnail).await {
44-
Ok(msg) => tracing::info!(msg),
45-
Err(msg) => tracing::info!(msg)
46-
};
47-
48-
tracing::info!("handler ends");
49-
50-
Ok(())
51-
*/
5238
}
5339

40+
#[cfg(not(test))]
5441
fn get_thumbnail(vec: Vec<u8>, size: u32) -> Vec<u8> {
55-
let reader = Cursor::new(vec);
56-
let mut thumbnails = create_thumbnails(reader, mime::IMAGE_PNG, [ThumbnailSize::Custom((size, size))]).unwrap();
42+
let reader = std::io::Cursor::new(vec);
43+
let mut thumbnails = thumbnailer::create_thumbnails(
44+
reader,
45+
mime::IMAGE_PNG,
46+
[thumbnailer::ThumbnailSize::Custom((size, size))],
47+
)
48+
.unwrap();
5749

5850
let thumbnail = thumbnails.pop().unwrap();
59-
let mut buf = Cursor::new(Vec::new());
51+
let mut buf = std::io::Cursor::new(Vec::new());
6052
thumbnail.write_png(&mut buf).unwrap();
6153

6254
buf.into_inner()
@@ -85,11 +77,17 @@ async fn main() -> Result<(), Error> {
8577
}
8678

8779
#[cfg(test)]
88-
mod tests {
89-
use std::fs::File;
90-
use std::io::BufReader;
91-
use std::io::Read;
80+
fn get_thumbnail(vec: Vec<u8>, _size: u32) -> Vec<u8> {
81+
let s = unsafe { std::str::from_utf8_unchecked(&vec) };
9282

83+
match s {
84+
"IMAGE" => "THUMBNAIL".into(),
85+
_ => "Input is not IMAGE".into(),
86+
}
87+
}
88+
89+
#[cfg(test)]
90+
mod tests {
9391
use super::*;
9492
use async_trait::async_trait;
9593
use aws_lambda_events::s3::object_lambda::Configuration;
@@ -122,13 +120,12 @@ mod tests {
122120
let mut mock = MockFakeS3Client::new();
123121

124122
mock.expect_get_file()
125-
.withf(|u: &String| u.eq("S3_URL"))
126-
.returning(|_1| Ok(get_file("testdata/image.png")));
123+
.withf(|u| u.eq("S3_URL"))
124+
.returning(|_1| Ok("IMAGE".into()));
127125

128126
mock.expect_send_file()
129-
.withf(|r: &String, t: &String, by| {
130-
let thumbnail = get_file("testdata/thumbnail.png");
131-
return r.eq("O_ROUTE") && t.eq("O_TOKEN") && by == &thumbnail;
127+
.withf(|r, t, by| {
128+
return r.eq("O_ROUTE") && t.eq("O_TOKEN") && by == "THUMBNAIL".as_bytes();
132129
})
133130
.returning(|_1, _2, _3| Ok("File sent.".to_string()));
134131

@@ -141,16 +138,6 @@ mod tests {
141138
assert_eq!(("File sent."), result);
142139
}
143140

144-
fn get_file(name: &str) -> Vec<u8> {
145-
let f = File::open(name);
146-
let mut reader = BufReader::new(f.unwrap());
147-
let mut buffer = Vec::new();
148-
149-
reader.read_to_end(&mut buffer).unwrap();
150-
151-
return buffer;
152-
}
153-
154141
fn get_s3_event() -> S3ObjectLambdaEvent {
155142
return S3ObjectLambdaEvent {
156143
x_amz_request_id: ("ID".to_string()),

examples/basic-s3-thumbnail/Cargo.toml

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,14 +20,15 @@ lambda_runtime = { path = "../../lambda-runtime" }
2020
serde = "1"
2121
tokio = { version = "1", features = ["macros"] }
2222
tracing = { version = "0.1" }
23-
tracing-subscriber = { version = "0.3", default-features = false, features = ["fmt"] }
24-
aws-config = "0.54.1"
25-
aws-sdk-s3 = "0.24.0"
23+
tracing-subscriber = { version = "0.3", default-features = false, features = ["ansi", "fmt"] }
24+
aws-config = "0.55"
25+
aws-smithy-http = "0.55.3"
26+
aws-sdk-s3 = "0.28"
2627
thumbnailer = "0.4.0"
2728
mime = "0.3.16"
28-
async-trait = "0.1.66"
29+
async-trait = "0.1.68"
2930

3031
[dev-dependencies]
31-
mockall = "0.11.3"
32-
tokio-test = "0.4.2"
32+
mockall = "0.11"
33+
tokio-test = "0.4"
3334
chrono = "0.4"

examples/basic-s3-thumbnail/README.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,22 @@ it downloads the created file, generates a thumbnail from it
55
(it assumes that the file is an image) and uploads it to S3 into a bucket named
66
[original-bucket-name]-thumbs.
77

8+
## Set up
9+
1. Create a lambda function and upload the bootloader.zip
10+
2. Go to aws services S3
11+
3. Create a bucket, let's say with name bucketx
12+
4. Create another bucket bucketx-thumbs
13+
5. Got to the bucketx properties tab, event notifications
14+
6. Create lambda event notification for "all object create event" and select your lambda function
15+
7. Go to the lambda function, configuration and open the role name
16+
8. Add "AmazonS3FullAccess" permission
17+
18+
## Test
19+
20+
1. Go to S3 and upload a png picture into bucketx. Beware to not have spaces or any special characters in the file name
21+
2. Go to S3 bucketx-thumbs and check if an image is created there.
22+
23+
824
## Build & Deploy
925

1026
1. Install [cargo-lambda](https://github.com/cargo-lambda/cargo-lambda#installation)

examples/basic-s3-thumbnail/src/main.rs

Lines changed: 21 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,7 @@
1-
use std::io::Cursor;
2-
31
use aws_lambda_events::{event::s3::S3Event, s3::S3EventRecord};
42
use aws_sdk_s3::Client as S3Client;
53
use lambda_runtime::{run, service_fn, Error, LambdaEvent};
64
use s3::{GetFile, PutFile};
7-
use thumbnailer::{create_thumbnails, ThumbnailSize};
85

96
mod s3;
107

@@ -86,7 +83,12 @@ fn get_file_props(record: S3EventRecord) -> Result<(String, String), String> {
8683
Ok((bucket, key))
8784
}
8885

86+
#[cfg(not(test))]
8987
fn get_thumbnail(vec: Vec<u8>, size: u32) -> Result<Vec<u8>, String> {
88+
use std::io::Cursor;
89+
90+
use thumbnailer::{create_thumbnails, ThumbnailSize};
91+
9092
let reader = Cursor::new(vec);
9193
let mime = mime::IMAGE_PNG;
9294
let sizes = [ThumbnailSize::Custom((size, size))];
@@ -126,12 +128,19 @@ async fn main() -> Result<(), Error> {
126128
Ok(())
127129
}
128130

131+
#[cfg(test)]
132+
fn get_thumbnail(vec: Vec<u8>, _size: u32) -> Result<Vec<u8>, String> {
133+
let s = unsafe { std::str::from_utf8_unchecked(&vec) };
134+
135+
match s {
136+
"IMAGE" => Ok("THUMBNAIL".into()),
137+
_ => Err("Input is not IMAGE".to_string()),
138+
}
139+
}
140+
129141
#[cfg(test)]
130142
mod tests {
131143
use std::collections::HashMap;
132-
use std::fs::File;
133-
use std::io::BufReader;
134-
use std::io::Read;
135144

136145
use super::*;
137146
use async_trait::async_trait;
@@ -141,7 +150,7 @@ mod tests {
141150
use aws_lambda_events::s3::S3Object;
142151
use aws_lambda_events::s3::S3RequestParameters;
143152
use aws_lambda_events::s3::S3UserIdentity;
144-
use aws_sdk_s3::error::GetObjectError;
153+
use aws_sdk_s3::operation::get_object::GetObjectError;
145154
use lambda_runtime::{Context, LambdaEvent};
146155
use mockall::mock;
147156
use s3::GetFile;
@@ -171,15 +180,14 @@ mod tests {
171180
let mut mock = MockFakeS3Client::new();
172181

173182
mock.expect_get_file()
174-
.withf(|b: &str, k: &str| b.eq(bucket) && k.eq(key))
175-
.returning(|_1, _2| Ok(get_file("testdata/image.png")));
183+
.withf(|b, k| b.eq(bucket) && k.eq(key))
184+
.returning(|_1, _2| Ok("IMAGE".into()));
176185

177186
mock.expect_put_file()
178-
.withf(|bu: &str, ke: &str, by| {
179-
let thumbnail = get_file("testdata/thumbnail.png");
180-
return bu.eq("test-bucket-thumbs") && ke.eq(key) && by == &thumbnail;
187+
.withf(|bu, ke, by| {
188+
return bu.eq("test-bucket-thumbs") && ke.eq(key) && by.eq("THUMBNAIL".as_bytes());
181189
})
182-
.returning(|_1, _2, _3| Ok("Done".to_string()));
190+
.return_const(Ok("Done".to_string()));
183191

184192
let payload = get_s3_event("ObjectCreated", bucket, key);
185193
let event = LambdaEvent { payload, context };
@@ -189,16 +197,6 @@ mod tests {
189197
assert_eq!((), result);
190198
}
191199

192-
fn get_file(name: &str) -> Vec<u8> {
193-
let f = File::open(name);
194-
let mut reader = BufReader::new(f.unwrap());
195-
let mut buffer = Vec::new();
196-
197-
reader.read_to_end(&mut buffer).unwrap();
198-
199-
return buffer;
200-
}
201-
202200
fn get_s3_event(event_name: &str, bucket_name: &str, object_key: &str) -> S3Event {
203201
return S3Event {
204202
records: (vec![get_s3_event_record(event_name, bucket_name, object_key)]),

examples/basic-s3-thumbnail/src/s3.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
use async_trait::async_trait;
2-
use aws_sdk_s3::{error::GetObjectError, types::ByteStream, Client as S3Client};
2+
use aws_sdk_s3::operation::get_object::GetObjectError;
3+
use aws_sdk_s3::Client as S3Client;
4+
use aws_smithy_http::byte_stream::ByteStream;
35

46
#[async_trait]
57
pub trait GetFile {
-282 Bytes
Binary file not shown.
-82 Bytes
Binary file not shown.

0 commit comments

Comments
 (0)