chromium/components/policy/core/common/android/policy_converter_unittest.cc

// Copyright 2015 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "components/policy/core/common/android/policy_converter.h"

#include <stddef.h>

#include "base/android/jni_android.h"
#include "base/android/jni_array.h"
#include "base/android/jni_string.h"
#include "base/json/json_writer.h"
#include "base/types/expected_macros.h"
#include "base/values.h"
#include "components/policy/core/common/schema.h"
#include "testing/gtest/include/gtest/gtest.h"

using base::Value;
using base::android::JavaRef;
using base::android::ScopedJavaLocalRef;

namespace policy {
namespace android {

class PolicyConverterTest : public testing::Test {
 public:
  void SetUp() override {
    const char kSchemaTemplate[] =
        R"({
        "type": "object",
        "properties": {
          "string": { "type": "string" },
          "int": { "type": "integer" },
          "bool": { "type": "boolean" },
          "double": { "type": "number" },
          "list": {
            "type": "array",
            "items": { "type": "string" }
          },
          "dict": { "type": "object" }
        }
      })";
    ASSIGN_OR_RETURN(schema_, Schema::Parse(kSchemaTemplate),
                     [](const auto& e) { ADD_FAILURE() << e; });
  }

 protected:
  // Converts the passed in value to the passed in schema, and serializes the
  // result to JSON, to make it easier to compare with EXPECT_EQ.
  std::string Convert(Value value, const Schema& value_schema) {
    std::optional<base::Value> converted_value =
        PolicyConverter::ConvertValueToSchema(std::move(value), value_schema);
    EXPECT_TRUE(converted_value.has_value());

    std::string json_string;
    EXPECT_TRUE(base::JSONWriter::Write(converted_value.value(), &json_string));
    return json_string;
  }

  // Uses `PolicyConverter::ConvertJavaStringArrayToListValue` to convert the
  // passed in java array and serializes the result to JSON, to make it easier
  // to compare with `EXPECT_EQ`.
  std::string ConvertJavaStringArrayToListValue(
      JNIEnv* env,
      const JavaRef<jobjectArray>& java_array) {
    base::Value::List list =
        PolicyConverter::ConvertJavaStringArrayToListValue(env, java_array);

    std::string json_string;
    EXPECT_TRUE(base::JSONWriter::Write(list, &json_string));

    return json_string;
  }

  // Converts the passed in values to a java string array
  ScopedJavaLocalRef<jobjectArray> MakeJavaStringArray(
      JNIEnv* env,
      std::vector<std::string> values) {
    jobjectArray java_array = (jobjectArray)env->NewObjectArray(
        values.size(), jni_zero::g_string_class, nullptr);
    for (size_t i = 0; i < values.size(); i++) {
      env->SetObjectArrayElement(
          java_array, i,
          base::android::ConvertUTF8ToJavaString(env, values[i]).obj());
    }

    return ScopedJavaLocalRef<jobjectArray>(env, java_array);
  }

  Schema schema_;
};

TEST_F(PolicyConverterTest, ConvertToBoolValue) {
  Schema bool_schema = schema_.GetKnownProperty("bool");
  ASSERT_TRUE(bool_schema.valid());

  EXPECT_EQ("true", Convert(Value(true), bool_schema));
  EXPECT_EQ("false", Convert(Value(false), bool_schema));
  EXPECT_EQ("true", Convert(Value("true"), bool_schema));
  EXPECT_EQ("false", Convert(Value("false"), bool_schema));
  EXPECT_EQ("\"narf\"", Convert(Value("narf"), bool_schema));
  EXPECT_EQ("false", Convert(Value(0), bool_schema));
  EXPECT_EQ("true", Convert(Value(1), bool_schema));
  EXPECT_EQ("true", Convert(Value(42), bool_schema));
  EXPECT_EQ("true", Convert(Value(-1), bool_schema));
  EXPECT_EQ("\"1\"", Convert(Value("1"), bool_schema));
  EXPECT_EQ("{}", Convert(Value(Value::Type::DICT), bool_schema));
}

TEST_F(PolicyConverterTest, ConvertToIntValue) {
  Schema int_schema = schema_.GetKnownProperty("int");
  ASSERT_TRUE(int_schema.valid());

  EXPECT_EQ("23", Convert(Value(23), int_schema));
  EXPECT_EQ("42", Convert(Value("42"), int_schema));
  EXPECT_EQ("-1", Convert(Value("-1"), int_schema));
  EXPECT_EQ("\"poit\"", Convert(Value("poit"), int_schema));
  EXPECT_EQ("false", Convert(Value(false), int_schema));
}

TEST_F(PolicyConverterTest, ConvertToDoubleValue) {
  Schema double_schema = schema_.GetKnownProperty("double");
  ASSERT_TRUE(double_schema.valid());

  EXPECT_EQ("3", Convert(Value(3), double_schema));
  EXPECT_EQ("3.14", Convert(Value(3.14), double_schema));
  EXPECT_EQ("2.71", Convert(Value("2.71"), double_schema));
  EXPECT_EQ("\"zort\"", Convert(Value("zort"), double_schema));
  EXPECT_EQ("true", Convert(Value(true), double_schema));
}

TEST_F(PolicyConverterTest, ConvertToStringValue) {
  Schema string_schema = schema_.GetKnownProperty("string");
  ASSERT_TRUE(string_schema.valid());

  EXPECT_EQ("\"troz\"", Convert(Value("troz"), string_schema));
  EXPECT_EQ("4711", Convert(Value(4711), string_schema));
}

TEST_F(PolicyConverterTest, ConvertToListValue) {
  Schema list_schema = schema_.GetKnownProperty("list");
  ASSERT_TRUE(list_schema.valid());

  Value::List list;
  list.Append("foo");
  list.Append("bar");
  EXPECT_EQ("[\"foo\",\"bar\"]", Convert(Value(std::move(list)), list_schema));
  EXPECT_EQ("[\"baz\",\"blurp\"]",
            Convert(Value("[\"baz\", \"blurp\"]"), list_schema));
  EXPECT_EQ("[\"hurz\"]", Convert(Value("hurz"), list_schema));
  EXPECT_EQ("[\"foo\",\"bar\"]", Convert(Value("foo,bar"), list_schema));
  EXPECT_EQ("[\"foo\",\"bar\"]", Convert(Value("foo, bar"), list_schema));
  EXPECT_EQ("19", Convert(Value(19), list_schema));

  EXPECT_FALSE(PolicyConverter::ConvertValueToSchema(Value(""), list_schema)
                   .has_value());
}

TEST_F(PolicyConverterTest, ConvertFromJavaListToListValue) {
  JNIEnv* env = base::android::AttachCurrentThread();
  EXPECT_EQ("[\"foo\",\"bar\",\"baz\"]",
            ConvertJavaStringArrayToListValue(
                env, MakeJavaStringArray(env, {"foo", "bar", "baz"})));
  EXPECT_EQ("[]", ConvertJavaStringArrayToListValue(
                      env, MakeJavaStringArray(env, {})));
}

TEST_F(PolicyConverterTest, ConvertToDictValue) {
  Schema dict_schema = schema_.GetKnownProperty("dict");
  ASSERT_TRUE(dict_schema.valid());

  base::Value::Dict dict;
  dict.Set("thx", 1138);
  EXPECT_EQ("{\"thx\":1138}", Convert(Value(std::move(dict)), dict_schema));
  EXPECT_EQ("{\"moose\":true}",
            Convert(Value("{\"moose\": true}"), dict_schema));
  EXPECT_EQ("\"fnord\"", Convert(Value("fnord"), dict_schema));
  EXPECT_EQ("1729", Convert(Value(1729), dict_schema));

  EXPECT_FALSE(PolicyConverter::ConvertValueToSchema(Value(""), dict_schema)
                   .has_value());
}

}  // namespace android
}  // namespace policy