Repository: jorgecarleitao/arrow2
Pull request #300 (2021-08-19 07:51:14)

Added tests to scalar API

codecov[bot]: # [Codecov](https://codecov.io/gh/jorgecarleitao/arrow2/pull/300?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Jorge+Leitao) Report
> Merging [#300](https://codecov.io/gh/jorgecarleitao/arrow2/pull/300?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Jorge+Leitao) (beaf307) into [main](https://codecov.io/gh/jorgecarleitao/arrow2/commit/8ff8f7d6ae1ec42c04e0517374eb594571afa1f0?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Jorge+Leitao) (8ff8f7d) will **increase** coverage by `0.29%`.
> The diff coverage is `100.00%`.

[![Impacted file tree graph](https://codecov.io/gh/jorgecarleitao/arrow2/pull/300/graphs/tree.svg?width=650&height=150&src=pr&token=AgyTF60R3D&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Jorge+Leitao)](https://codecov.io/gh/jorgecarleitao/arrow2/pull/300?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Jorge+Leitao)

```diff
@@            Coverage Diff             @@
##             main     #300      +/-   ##
==========================================
+ Coverage   80.23%   80.52%   +0.29%     
==========================================
  Files         316      323       +7     
  Lines       21067    21135      +68     
==========================================
+ Hits        16903    17019     +116     
+ Misses       4164     4116      -48     
```


| [Impacted Files](https://codecov.io/gh/jorgecarleitao/arrow2/pull/300?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Jorge+Leitao) | Coverage Δ | |
|---|---|---|
| [src/scalar/binary.rs](https://codecov.io/gh/jorgecarleitao/arrow2/pull/300/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Jorge+Leitao#diff-c3JjL3NjYWxhci9iaW5hcnkucnM=) | `94.44% <ø> (-2.70%)` | :arrow_down: |
| [src/scalar/boolean.rs](https://codecov.io/gh/jorgecarleitao/arrow2/pull/300/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Jorge+Leitao#diff-c3JjL3NjYWxhci9ib29sZWFuLnJz) | `86.66% <ø> (-6.44%)` | :arrow_down: |
| [src/scalar/primitive.rs](https://codecov.io/gh/jorgecarleitao/arrow2/pull/300/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Jorge+Leitao#diff-c3JjL3NjYWxhci9wcmltaXRpdmUucnM=) | `90.90% <ø> (-4.44%)` | :arrow_down: |
| [src/scalar/utf8.rs](https://codecov.io/gh/jorgecarleitao/arrow2/pull/300/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Jorge+Leitao#diff-c3JjL3NjYWxhci91dGY4LnJz) | `94.44% <ø> (-2.70%)` | :arrow_down: |
| [tests/it/array/boolean/mutable.rs](https://codecov.io/gh/jorgecarleitao/arrow2/pull/300/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Jorge+Leitao#diff-dGVzdHMvaXQvYXJyYXkvYm9vbGVhbi9tdXRhYmxlLnJz) | `100.00% <100.00%> (ø)` | |
| [tests/it/array/growable/struct\_.rs](https://codecov.io/gh/jorgecarleitao/arrow2/pull/300/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Jorge+Leitao#diff-dGVzdHMvaXQvYXJyYXkvZ3Jvd2FibGUvc3RydWN0Xy5ycw==) | `100.00% <100.00%> (ø)` | |
| [tests/it/scalar/binary.rs](https://codecov.io/gh/jorgecarleitao/arrow2/pull/300/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Jorge+Leitao#diff-dGVzdHMvaXQvc2NhbGFyL2JpbmFyeS5ycw==) | `100.00% <100.00%> (ø)` | |
| [tests/it/scalar/boolean.rs](https://codecov.io/gh/jorgecarleitao/arrow2/pull/300/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Jorge+Leitao#diff-dGVzdHMvaXQvc2NhbGFyL2Jvb2xlYW4ucnM=) | `100.00% <100.00%> (ø)` | |
| [tests/it/scalar/list.rs](https://codecov.io/gh/jorgecarleitao/arrow2/pull/300/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Jorge+Leitao#diff-dGVzdHMvaXQvc2NhbGFyL2xpc3QucnM=) | `100.00% <100.00%> (ø)` | |
| [tests/it/scalar/null.rs](https://codecov.io/gh/jorgecarleitao/arrow2/pull/300/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Jorge+Leitao#diff-dGVzdHMvaXQvc2NhbGFyL251bGwucnM=) | `100.00% <100.00%> (ø)` | |
| ... and [15 more](https://codecov.io/gh/jorgecarleitao/arrow2/pull/300/diff?src=pr&el=tree-more&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Jorge+Leitao) | |

------

[Continue to review full report at Codecov](https://codecov.io/gh/jorgecarleitao/arrow2/pull/300?src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Jorge+Leitao).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Jorge+Leitao)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/jorgecarleitao/arrow2/pull/300?src=pr&el=footer&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Jorge+Leitao). Last update [8ff8f7d...beaf307](https://codecov.io/gh/jorgecarleitao/arrow2/pull/300?src=pr&el=lastupdated&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Jorge+Leitao). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Jorge+Leitao).


Patch:
diff --git a/README.md b/README.md
index 61a5c5439d..18b946ae63 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,7 @@
 # Arrow2: Transmute-free Arrow
 
 [![test](https://github.com/jorgecarleitao/arrow2/actions/workflows/test.yml/badge.svg)](https://github.com/jorgecarleitao/arrow2/actions/workflows/Build.yml)
+[![codecov](https://codecov.io/gh/jorgecarleitao/arrow2/branch/main/graph/badge.svg?token=AgyTF60R3D)](https://codecov.io/gh/jorgecarleitao/arrow2)
 [![](https://img.shields.io/crates/d/arrow2.svg)](https://crates.io/crates/arrow2)
 [![](https://img.shields.io/crates/dv/arrow2.svg)](https://crates.io/crates/arrow2)
 [![](https://docs.rs/arrow2/badge.svg)](https://docs.rs/arrow2/)
diff --git a/src/scalar/binary.rs b/src/scalar/binary.rs
index fbd769f9d5..f847e8f0c8 100644
--- a/src/scalar/binary.rs
+++ b/src/scalar/binary.rs
@@ -61,35 +61,3 @@ impl<O: Offset> Scalar for BinaryScalar<O> {
         }
     }
 }
-
-#[cfg(test)]
-mod tests {
-    use super::*;
-
-    #[allow(clippy::eq_op)]
-    #[test]
-    fn equal() {
-        let a = BinaryScalar::<i32>::from(Some("a"));
-        let b = BinaryScalar::<i32>::from(None::<&str>);
-        assert_eq!(a, a);
-        assert_eq!(b, b);
-        assert!(a != b);
-        let b = BinaryScalar::<i32>::from(Some("b"));
-        assert!(a != b);
-        assert_eq!(b, b);
-    }
-
-    #[test]
-    fn basics() {
-        let a = BinaryScalar::<i32>::from(Some("a"));
-
-        assert_eq!(a.value(), b"a");
-        assert_eq!(a.data_type(), &DataType::Binary);
-        assert!(a.is_valid());
-
-        let a = BinaryScalar::<i64>::from(None::<&str>);
-
-        assert_eq!(a.data_type(), &DataType::LargeBinary);
-        assert!(!a.is_valid());
-    }
-}
diff --git a/src/scalar/boolean.rs b/src/scalar/boolean.rs
index 67137c752f..7f0ffdaa0d 100644
--- a/src/scalar/boolean.rs
+++ b/src/scalar/boolean.rs
@@ -53,30 +53,3 @@ impl From<Option<bool>> for BooleanScalar {
         Self::new(v)
     }
 }
-
-#[cfg(test)]
-mod tests {
-    use super::*;
-
-    #[allow(clippy::eq_op)]
-    #[test]
-    fn equal() {
-        let a = BooleanScalar::from(Some(true));
-        let b = BooleanScalar::from(None);
-        assert_eq!(a, a);
-        assert_eq!(b, b);
-        assert!(a != b);
-        let b = BooleanScalar::from(Some(false));
-        assert!(a != b);
-        assert_eq!(b, b);
-    }
-
-    #[test]
-    fn basics() {
-        let a = BooleanScalar::new(Some(true));
-
-        assert!(a.value());
-        assert_eq!(a.data_type(), &DataType::Boolean);
-        assert!(a.is_valid());
-    }
-}
diff --git a/src/scalar/primitive.rs b/src/scalar/primitive.rs
index b204a774ef..90265bf7cb 100644
--- a/src/scalar/primitive.rs
+++ b/src/scalar/primitive.rs
@@ -73,41 +73,3 @@ impl<T: NativeType> Scalar for PrimitiveScalar<T> {
         &self.data_type
     }
 }
-
-#[cfg(test)]
-mod tests {
-    use super::*;
-
-    #[allow(clippy::eq_op)]
-    #[test]
-    fn equal() {
-        let a = PrimitiveScalar::from(Some(2i32));
-        let b = PrimitiveScalar::<i32>::from(None);
-        assert_eq!(a, a);
-        assert_eq!(b, b);
-        assert!(a != b);
-        let b = PrimitiveScalar::<i32>::from(Some(1i32));
-        assert!(a != b);
-        assert_eq!(b, b);
-    }
-
-    #[test]
-    fn basics() {
-        let a = PrimitiveScalar::from(Some(2i32));
-
-        assert_eq!(a.value(), 2i32);
-        assert_eq!(a.data_type(), &DataType::Int32);
-        assert!(a.is_valid());
-
-        let a = a.to(DataType::Date32);
-        assert_eq!(a.data_type(), &DataType::Date32);
-
-        let a = PrimitiveScalar::<i32>::from(None);
-
-        assert_eq!(a.data_type(), &DataType::Int32);
-        assert!(!a.is_valid());
-
-        let a = a.to(DataType::Date32);
-        assert_eq!(a.data_type(), &DataType::Date32);
-    }
-}
diff --git a/src/scalar/utf8.rs b/src/scalar/utf8.rs
index 32fe5d7f1b..207fe084f0 100644
--- a/src/scalar/utf8.rs
+++ b/src/scalar/utf8.rs
@@ -61,35 +61,3 @@ impl<O: Offset> Scalar for Utf8Scalar<O> {
         }
     }
 }
-
-#[cfg(test)]
-mod tests {
-    use super::*;
-
-    #[allow(clippy::eq_op)]
-    #[test]
-    fn equal() {
-        let a = Utf8Scalar::<i32>::from(Some("a"));
-        let b = Utf8Scalar::<i32>::from(None::<&str>);
-        assert_eq!(a, a);
-        assert_eq!(b, b);
-        assert!(a != b);
-        let b = Utf8Scalar::<i32>::from(Some("b"));
-        assert!(a != b);
-        assert_eq!(b, b);
-    }
-
-    #[test]
-    fn basics() {
-        let a = Utf8Scalar::<i32>::from(Some("a"));
-
-        assert_eq!(a.value(), "a");
-        assert_eq!(a.data_type(), &DataType::Utf8);
-        assert!(a.is_valid());
-
-        let a = Utf8Scalar::<i64>::from(None::<&str>);
-
-        assert_eq!(a.data_type(), &DataType::LargeUtf8);
-        assert!(!a.is_valid());
-    }
-}


Test patch:
diff --git a/tests/it/array/boolean/mutable.rs b/tests/it/array/boolean/mutable.rs
index 07c4a7e54e..70ca6845f2 100644
--- a/tests/it/array/boolean/mutable.rs
+++ b/tests/it/array/boolean/mutable.rs
@@ -1,4 +1,5 @@
 use arrow2::array::{MutableArray, MutableBooleanArray};
+use arrow2::bitmap::MutableBitmap;
 use arrow2::error::Result;
 
 #[test]
@@ -10,7 +11,8 @@ fn set() {
     assert_eq!(
         a,
         MutableBooleanArray::from([Some(true), None, Some(false)])
-    )
+    );
+    assert_eq!(a.values(), &MutableBitmap::from([true, false, false]));
 }
 
 #[test]
@@ -42,7 +44,18 @@ fn from_iter() {
 
 #[test]
 fn try_from_trusted_len_iter() {
-    let iter = std::iter::repeat(Some(true)).take(2).map(Result::Ok);
+    let iter = vec![Some(true), Some(true), None]
+        .into_iter()
+        .map(Result::Ok);
     let a = MutableBooleanArray::try_from_trusted_len_iter(iter).unwrap();
-    assert_eq!(a, MutableBooleanArray::from([Some(true), Some(true)]));
+    assert_eq!(a, MutableBooleanArray::from([Some(true), Some(true), None]));
+}
+
+#[test]
+fn reserve() {
+    let mut a = MutableBooleanArray::from_data(MutableBitmap::new(), Some(MutableBitmap::new()));
+
+    a.reserve(10);
+    assert!(a.validity().as_ref().unwrap().capacity() > 0);
+    assert!(a.values().capacity() > 0)
 }
diff --git a/tests/it/array/growable/struct_.rs b/tests/it/array/growable/struct_.rs
index ed5e715c46..f26e4c08ae 100644
--- a/tests/it/array/growable/struct_.rs
+++ b/tests/it/array/growable/struct_.rs
@@ -98,22 +98,32 @@ fn many() {
 
     let array = StructArray::from_data(fields.clone(), values.clone(), None);
 
-    let mut mutable = GrowableStruct::new(vec![&array, &array], false, 0);
+    let mut mutable = GrowableStruct::new(vec![&array, &array], true, 0);
 
     mutable.extend(0, 1, 2);
     mutable.extend(1, 0, 2);
-    let result: StructArray = mutable.into();
+    mutable.extend_validity(1);
+    let result = mutable.as_box();
 
     let expected_string: Arc<dyn Array> = Arc::new(Utf8Array::<i32>::from(&[
         Some("aa"),
         None,
         Some("a"),
         Some("aa"),
+        None,
+    ]));
+    let expected_int: Arc<dyn Array> = Arc::new(PrimitiveArray::<i32>::from(vec![
+        Some(2),
+        Some(3),
+        Some(1),
+        Some(2),
+        None,
     ]));
-    let expected_int: Arc<dyn Array> = Arc::new(
-        PrimitiveArray::<i32>::from(vec![Some(2), Some(3), Some(1), Some(2)]).to(DataType::Int32),
-    );
 
-    let expected = StructArray::from_data(fields, vec![expected_string, expected_int], None);
-    assert_eq!(result, expected)
+    let expected = StructArray::from_data(
+        fields,
+        vec![expected_string, expected_int],
+        Some(Bitmap::from([true, true, true, true, false])),
+    );
+    assert_eq!(expected, result.as_ref())
 }
diff --git a/tests/it/main.rs b/tests/it/main.rs
index b1501a9f24..ad9a9b9735 100644
--- a/tests/it/main.rs
+++ b/tests/it/main.rs
@@ -3,8 +3,10 @@ mod array;
 mod bitmap;
 mod buffer;
 mod ffi;
+mod scalar;
 
 mod io;
 mod test_util;
 
+#[cfg(feature = "compute")]
 mod compute;
diff --git a/tests/it/scalar/binary.rs b/tests/it/scalar/binary.rs
new file mode 100644
index 0000000000..5abaf7a3a7
--- /dev/null
+++ b/tests/it/scalar/binary.rs
@@ -0,0 +1,33 @@
+use arrow2::{
+    datatypes::DataType,
+    scalar::{BinaryScalar, Scalar},
+};
+
+#[allow(clippy::eq_op)]
+#[test]
+fn equal() {
+    let a = BinaryScalar::<i32>::from(Some("a"));
+    let b = BinaryScalar::<i32>::from(None::<&str>);
+    assert_eq!(a, a);
+    assert_eq!(b, b);
+    assert!(a != b);
+    let b = BinaryScalar::<i32>::from(Some("b"));
+    assert!(a != b);
+    assert_eq!(b, b);
+}
+
+#[test]
+fn basics() {
+    let a = BinaryScalar::<i32>::from(Some("a"));
+
+    assert_eq!(a.value(), b"a");
+    assert_eq!(a.data_type(), &DataType::Binary);
+    assert!(a.is_valid());
+
+    let a = BinaryScalar::<i64>::from(None::<&str>);
+
+    assert_eq!(a.data_type(), &DataType::LargeBinary);
+    assert!(!a.is_valid());
+
+    let _: &dyn std::any::Any = a.as_any();
+}
diff --git a/tests/it/scalar/boolean.rs b/tests/it/scalar/boolean.rs
new file mode 100644
index 0000000000..a98b72210c
--- /dev/null
+++ b/tests/it/scalar/boolean.rs
@@ -0,0 +1,28 @@
+use arrow2::{
+    datatypes::DataType,
+    scalar::{BooleanScalar, Scalar},
+};
+
+#[allow(clippy::eq_op)]
+#[test]
+fn equal() {
+    let a = BooleanScalar::from(Some(true));
+    let b = BooleanScalar::from(None);
+    assert_eq!(a, a);
+    assert_eq!(b, b);
+    assert!(a != b);
+    let b = BooleanScalar::from(Some(false));
+    assert!(a != b);
+    assert_eq!(b, b);
+}
+
+#[test]
+fn basics() {
+    let a = BooleanScalar::new(Some(true));
+
+    assert!(a.value());
+    assert_eq!(a.data_type(), &DataType::Boolean);
+    assert!(a.is_valid());
+
+    let _: &dyn std::any::Any = a.as_any();
+}
diff --git a/tests/it/scalar/list.rs b/tests/it/scalar/list.rs
new file mode 100644
index 0000000000..9475a30a58
--- /dev/null
+++ b/tests/it/scalar/list.rs
@@ -0,0 +1,42 @@
+use std::sync::Arc;
+
+use arrow2::{
+    array::{Array, BooleanArray},
+    datatypes::{DataType, Field},
+    scalar::{ListScalar, Scalar},
+};
+
+#[allow(clippy::eq_op)]
+#[test]
+fn equal() {
+    let dt = DataType::List(Box::new(Field::new("a", DataType::Boolean, true)));
+    let a = ListScalar::<i32>::new(
+        dt.clone(),
+        Some(Arc::new(BooleanArray::from_slice([true, false])) as Arc<dyn Array>),
+    );
+    let b = ListScalar::<i32>::new(dt.clone(), None);
+    assert_eq!(a, a);
+    assert_eq!(b, b);
+    assert!(a != b);
+    let b = ListScalar::<i32>::new(
+        dt,
+        Some(Arc::new(BooleanArray::from_slice([true, true])) as Arc<dyn Array>),
+    );
+    assert!(a != b);
+    assert_eq!(b, b);
+}
+
+#[test]
+fn basics() {
+    let dt = DataType::List(Box::new(Field::new("a", DataType::Boolean, true)));
+    let a = ListScalar::<i32>::new(
+        dt.clone(),
+        Some(Arc::new(BooleanArray::from_slice([true, false])) as Arc<dyn Array>),
+    );
+
+    assert_eq!(BooleanArray::from_slice([true, false]), a.values().as_ref());
+    assert_eq!(a.data_type(), &dt);
+    assert!(a.is_valid());
+
+    let _: &dyn std::any::Any = a.as_any();
+}
diff --git a/tests/it/scalar/mod.rs b/tests/it/scalar/mod.rs
new file mode 100644
index 0000000000..f5fe233dd4
--- /dev/null
+++ b/tests/it/scalar/mod.rs
@@ -0,0 +1,7 @@
+mod binary;
+mod boolean;
+mod list;
+mod null;
+mod primitive;
+mod struct_;
+mod utf8;
diff --git a/tests/it/scalar/null.rs b/tests/it/scalar/null.rs
new file mode 100644
index 0000000000..685b237b80
--- /dev/null
+++ b/tests/it/scalar/null.rs
@@ -0,0 +1,21 @@
+use arrow2::{
+    datatypes::DataType,
+    scalar::{NullScalar, Scalar},
+};
+
+#[allow(clippy::eq_op)]
+#[test]
+fn equal() {
+    let a = NullScalar::new();
+    assert_eq!(a, a);
+}
+
+#[test]
+fn basics() {
+    let a = NullScalar::default();
+
+    assert_eq!(a.data_type(), &DataType::Null);
+    assert!(!a.is_valid());
+
+    let _: &dyn std::any::Any = a.as_any();
+}
diff --git a/tests/it/scalar/primitive.rs b/tests/it/scalar/primitive.rs
new file mode 100644
index 0000000000..c248689f3e
--- /dev/null
+++ b/tests/it/scalar/primitive.rs
@@ -0,0 +1,39 @@
+use arrow2::{
+    datatypes::DataType,
+    scalar::{PrimitiveScalar, Scalar},
+};
+
+#[allow(clippy::eq_op)]
+#[test]
+fn equal() {
+    let a = PrimitiveScalar::from(Some(2i32));
+    let b = PrimitiveScalar::<i32>::from(None);
+    assert_eq!(a, a);
+    assert_eq!(b, b);
+    assert!(a != b);
+    let b = PrimitiveScalar::<i32>::from(Some(1i32));
+    assert!(a != b);
+    assert_eq!(b, b);
+}
+
+#[test]
+fn basics() {
+    let a = PrimitiveScalar::from(Some(2i32));
+
+    assert_eq!(a.value(), 2i32);
+    assert_eq!(a.data_type(), &DataType::Int32);
+    assert!(a.is_valid());
+
+    let a = a.to(DataType::Date32);
+    assert_eq!(a.data_type(), &DataType::Date32);
+
+    let a = PrimitiveScalar::<i32>::from(None);
+
+    assert_eq!(a.data_type(), &DataType::Int32);
+    assert!(!a.is_valid());
+
+    let a = a.to(DataType::Date32);
+    assert_eq!(a.data_type(), &DataType::Date32);
+
+    let _: &dyn std::any::Any = a.as_any();
+}
diff --git a/tests/it/scalar/struct_.rs b/tests/it/scalar/struct_.rs
new file mode 100644
index 0000000000..9209afee8c
--- /dev/null
+++ b/tests/it/scalar/struct_.rs
@@ -0,0 +1,45 @@
+use std::sync::Arc;
+
+use arrow2::{
+    datatypes::{DataType, Field},
+    scalar::{BooleanScalar, Scalar, StructScalar},
+};
+
+#[allow(clippy::eq_op)]
+#[test]
+fn equal() {
+    let dt = DataType::Struct(vec![Field::new("a", DataType::Boolean, true)]);
+    let a = StructScalar::new(
+        dt.clone(),
+        Some(vec![
+            Arc::new(BooleanScalar::from(Some(true))) as Arc<dyn Scalar>
+        ]),
+    );
+    let b = StructScalar::new(dt.clone(), None);
+    assert_eq!(a, a);
+    assert_eq!(b, b);
+    assert!(a != b);
+    let b = StructScalar::new(
+        dt,
+        Some(vec![
+            Arc::new(BooleanScalar::from(Some(false))) as Arc<dyn Scalar>
+        ]),
+    );
+    assert!(a != b);
+    assert_eq!(b, b);
+}
+
+#[test]
+fn basics() {
+    let dt = DataType::Struct(vec![Field::new("a", DataType::Boolean, true)]);
+
+    let values = vec![Arc::new(BooleanScalar::from(Some(true))) as Arc<dyn Scalar>];
+
+    let a = StructScalar::new(dt.clone(), Some(values.clone()));
+
+    assert_eq!(a.values(), &values);
+    assert_eq!(a.data_type(), &dt);
+    assert!(a.is_valid());
+
+    let _: &dyn std::any::Any = a.as_any();
+}
diff --git a/tests/it/scalar/utf8.rs b/tests/it/scalar/utf8.rs
new file mode 100644
index 0000000000..edd95c6e24
--- /dev/null
+++ b/tests/it/scalar/utf8.rs
@@ -0,0 +1,33 @@
+use arrow2::{
+    datatypes::DataType,
+    scalar::{Scalar, Utf8Scalar},
+};
+
+#[allow(clippy::eq_op)]
+#[test]
+fn equal() {
+    let a = Utf8Scalar::<i32>::from(Some("a"));
+    let b = Utf8Scalar::<i32>::from(None::<&str>);
+    assert_eq!(a, a);
+    assert_eq!(b, b);
+    assert!(a != b);
+    let b = Utf8Scalar::<i32>::from(Some("b"));
+    assert!(a != b);
+    assert_eq!(b, b);
+}
+
+#[test]
+fn basics() {
+    let a = Utf8Scalar::<i32>::from(Some("a"));
+
+    assert_eq!(a.value(), "a");
+    assert_eq!(a.data_type(), &DataType::Utf8);
+    assert!(a.is_valid());
+
+    let a = Utf8Scalar::<i64>::from(None::<&str>);
+
+    assert_eq!(a.data_type(), &DataType::LargeUtf8);
+    assert!(!a.is_valid());
+
+    let _: &dyn std::any::Any = a.as_any();
+}