review fixes: change test attributes, fix tests, add time encoding-decoding tests

This commit is contained in:
Vlad Stepanov 2020-03-01 13:20:24 +03:00
parent 322393c9ee
commit b2f50de16f
5 changed files with 147 additions and 28 deletions

View File

@ -173,6 +173,67 @@ fn postgres_epoch() -> DateTime<Utc> {
Utc.ymd(2000, 1, 1).and_hms(0, 0, 0)
}
#[test]
fn test_encode_time() {
let mut buf = Vec::new();
Encode::<Postgres>::encode(&NaiveTime::from_hms(0, 0, 0), &mut buf);
assert_eq!(buf, [0; 8]);
buf.clear();
// one second
Encode::<Postgres>::encode(&NaiveTime::from_hms(0, 0, 1), &mut buf);
assert_eq!(buf, 1_000_000i64.to_be_bytes());
buf.clear();
// two hours
Encode::<Postgres>::encode(&NaiveTime::from_hms(2, 0, 0), &mut buf);
let expected = 1_000_000i64 * 60 * 60 * 2;
assert_eq!(buf, expected.to_be_bytes());
buf.clear();
// 3:14:15.000001
Encode::<Postgres>::encode(&NaiveTime::from_hms_micro(3, 14, 15, 1), &mut buf);
let expected =
1_000_000i64 * 60 * 60 * 3 +
1_000_000i64 * 60 * 14 +
1_000_000i64 * 15 +
1
;
assert_eq!(buf, expected.to_be_bytes());
buf.clear();
}
#[test]
fn test_decode_time() {
let buf = [0u8; 8];
let time: NaiveTime = Decode::<Postgres>::decode(&buf).unwrap();
assert_eq!(
time,
NaiveTime::from_hms(0, 0, 0),
);
// half an hour
let buf = (1_000_000i64 * 60 * 30).to_be_bytes();
let time: NaiveTime = Decode::<Postgres>::decode(&buf).unwrap();
assert_eq!(
time,
NaiveTime::from_hms(0, 30, 0),
);
// 12:53:05.125305
let buf = (
1_000_000i64 * 60 * 60 * 12 +
1_000_000i64 * 60 * 53 +
1_000_000i64 * 5 +
125305
).to_be_bytes();
let time: NaiveTime = Decode::<Postgres>::decode(&buf).unwrap();
assert_eq!(
time,
NaiveTime::from_hms_micro(12, 53, 5, 125305),
);
}
#[test]
fn test_encode_datetime() {
let mut buf = Vec::new();

View File

@ -60,14 +60,14 @@ impl HasSqlType<[OffsetDateTime]> for Postgres {
}
}
const fn microseconds_since_midnight(time: &Time) -> u64 {
time.hour() as u64 * 60 * 60 * 1_000_000
+ time.minute() as u64 * 60 * 1_000_000
+ time.second() as u64 * 1_000_000
+ time.microsecond() as u64
fn microseconds_since_midnight(time: Time) -> i64 {
time.hour() as i64 * 60 * 60 * 1_000_000
+ time.minute() as i64 * 60 * 1_000_000
+ time.second() as i64 * 1_000_000
+ time.microsecond() as i64
}
fn from_nanoseconds_since_midnight(mut microsecond: u64) -> Result<Time, DecodeError> {
fn from_microseconds_since_midnight(mut microsecond: u64) -> Result<Time, DecodeError> {
#![allow(clippy::cast_possible_truncation)]
microsecond %= 86_400 * 1_000_000;
@ -85,15 +85,15 @@ impl Decode<Postgres> for Time {
fn decode(raw: &[u8]) -> Result<Self, DecodeError> {
let micros: i64 = Decode::<Postgres>::decode(raw)?;
from_nanoseconds_since_midnight(micros as u64)
from_microseconds_since_midnight(micros as u64)
}
}
impl Encode<Postgres> for Time {
fn encode(&self, buf: &mut Vec<u8>) {
let micros = microseconds_since_midnight(&self) / 1000;
let micros = microseconds_since_midnight(*self);
Encode::<Postgres>::encode(&(micros as i64), buf);
Encode::<Postgres>::encode(&(micros), buf);
}
fn size_hint(&self) -> usize {
@ -171,6 +171,69 @@ impl Encode<Postgres> for OffsetDateTime {
#[cfg(test)]
use time::time;
#[test]
fn test_encode_time() {
let mut buf = Vec::new();
Encode::<Postgres>::encode(&time!(0:00), &mut buf);
assert_eq!(buf, [0; 8]);
buf.clear();
// one second
Encode::<Postgres>::encode(&time!(0:00:01), &mut buf);
assert_eq!(buf, 1_000_000i64.to_be_bytes());
buf.clear();
// two hours
Encode::<Postgres>::encode(&time!(2:00), &mut buf);
let expected = 1_000_000i64 * 60 * 60 * 2;
assert_eq!(buf, expected.to_be_bytes());
buf.clear();
// 3:14:15.000001
Encode::<Postgres>::encode(&time!(3:14:15.000001), &mut buf);
let expected =
1_000_000i64 * 60 * 60 * 3 +
1_000_000i64 * 60 * 14 +
1_000_000i64 * 15 +
1
;
assert_eq!(buf, expected.to_be_bytes());
buf.clear();
}
#[test]
fn test_decode_time() {
let buf = [0u8; 8];
let time: Time = Decode::<Postgres>::decode(&buf).unwrap();
assert_eq!(
time,
time!(0:00),
);
// half an hour
let buf = (1_000_000i64 * 60 * 30).to_be_bytes();
let time: Time = Decode::<Postgres>::decode(&buf).unwrap();
assert_eq!(
time,
time!(0:30),
);
// 12:53:05.125305
let buf = (
1_000_000i64 * 60 * 60 * 12 +
1_000_000i64 * 60 * 53 +
1_000_000i64 * 5 +
125305
).to_be_bytes();
let time: Time = Decode::<Postgres>::decode(&buf).unwrap();
assert_eq!(
time,
time!(12:53:05.125305),
);
}
#[test]
fn test_encode_datetime() {
let mut buf = Vec::new();

View File

@ -27,7 +27,6 @@ async fn mysql_chrono_date() -> anyhow::Result<()> {
Ok(())
}
#[cfg(all(feature = "chrono", not(feature = "time")))]
#[cfg_attr(feature = "runtime-async-std", async_std::test)]
#[cfg_attr(feature = "runtime-tokio", tokio::test)]
async fn mysql_chrono_date_time() -> anyhow::Result<()> {
@ -47,7 +46,6 @@ async fn mysql_chrono_date_time() -> anyhow::Result<()> {
Ok(())
}
#[cfg(all(feature = "chrono", not(feature = "time")))]
#[cfg_attr(feature = "runtime-async-std", async_std::test)]
#[cfg_attr(feature = "runtime-tokio", tokio::test)]
async fn mysql_chrono_time() -> anyhow::Result<()> {
@ -66,7 +64,6 @@ async fn mysql_chrono_time() -> anyhow::Result<()> {
Ok(())
}
#[cfg(all(feature = "chrono", not(feature = "time")))]
#[cfg_attr(feature = "runtime-async-std", async_std::test)]
#[cfg_attr(feature = "runtime-tokio", tokio::test)]
async fn mysql_chrono_timestamp() -> anyhow::Result<()> {

View File

@ -5,7 +5,6 @@ async fn connect() -> anyhow::Result<PgConnection> {
Ok(PgConnection::open(dotenv::var("DATABASE_URL")?).await?)
}
#[cfg(all(feature = "chrono", not(feature = "time")))]
#[cfg_attr(feature = "runtime-async-std", async_std::test)]
#[cfg_attr(feature = "runtime-tokio", tokio::test)]
async fn postgres_chrono_date() -> anyhow::Result<()> {
@ -24,7 +23,6 @@ async fn postgres_chrono_date() -> anyhow::Result<()> {
Ok(())
}
#[cfg(all(feature = "chrono", not(feature = "time")))]
#[cfg_attr(feature = "runtime-async-std", async_std::test)]
#[cfg_attr(feature = "runtime-tokio", tokio::test)]
async fn mysql_chrono_date_time() -> anyhow::Result<()> {
@ -51,18 +49,18 @@ async fn postgres_chrono_time() -> anyhow::Result<()> {
let value = NaiveTime::from_hms_micro(5, 10, 20, 115100);
let row = sqlx::query("SELECT TIME '05:10:20.115100' = $1, TIME '05:10:20.115100'")
.bind(&value)
.fetch_one(&mut conn)
.await?;
let row = sqlx::query!(
"SELECT TIME '05:10:20.115100' = $1 AS equality, TIME '05:10:20.115100' AS time"
)
.fetch_one(&mut conn)
.await?;
assert!(row.get::<bool, _>(0));
assert_eq!(value, row.get(1));
assert!(row.equality);
assert_eq!(value, row.time);
Ok(())
}
#[cfg(all(feature = "chrono", not(feature = "time")))]
#[cfg_attr(feature = "runtime-async-std", async_std::test)]
#[cfg_attr(feature = "runtime-tokio", tokio::test)]
async fn postgres_chrono_timestamp_tz() -> anyhow::Result<()> {

View File

@ -51,14 +51,14 @@ async fn postgres_timers_time() -> anyhow::Result<()> {
let value = Time::try_from_hms_micro(5, 10, 20, 115100).unwrap();
let row = sqlx::query("SELECT TIME '05:10:20.115100' = $1, TIME '05:10:20.115100'")
.bind(&value)
.fetch_one(&mut conn)
.await?;
let row = sqlx::query!(
"SELECT TIME '05:10:20.115100' = $1 AS equality, TIME '05:10:20.115100' AS time", value
)
.fetch_one(&mut conn)
.await?;
// FIXME: line 60 fails, while assertion on line 61 holds true (???)
// assert!(row.get::<bool, _>(0));
assert_eq!(value, row.get(1));
assert!(row.equality);
assert_eq!(value, row.time);
Ok(())
}