You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@couchdb.apache.org by va...@apache.org on 2023/03/16 13:42:31 UTC

[couchdb] branch main updated: Improve couch_js_tests

This is an automated email from the ASF dual-hosted git repository.

vatamane pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/couchdb.git


The following commit(s) were added to refs/heads/main by this push:
     new b9762479f Improve couch_js_tests
b9762479f is described below

commit b9762479fa9dd43bfa799ac4eb60f7394aa999ea
Author: Nick Vatamaniuc <va...@gmail.com>
AuthorDate: Thu Mar 16 01:42:52 2023 -0400

    Improve couch_js_tests
    
    There are a few minor improvements:
    
    - Add more tests to check sandboxing resets, and that docs are "frozen".
    
    - Remove the extra `\n` and `"` around function body lines. Erlang can do
      multi-line binaries just fine. Mark the sections with %erlfmt-ignore to the
      formatter doesn't complain.
    
    - Generalize `should_create_sandbox` test to check for the `not defined` string
      only. Experimenting with QuickJS noticed that it uses single quotes
      around`'Object.foo' is not defined` and SM doesn't. So check for `not
      defined` part only as it's obvious enough what the check is about.
    
    - Make sure to return test procs back to the pool. Previously, none of the
      tests returned the processes back into the pool, and when the tests ended,
      they were forcibly killed which resulted in log noise that looked like:
    
    ```
    erl_child_setup: failed with error 32 on line 265
    erl_child_setup: failed with error 32 on line 265
    ...
    ```
---
 src/couch/test/eunit/couch_js_tests.erl | 171 +++++++++++++++++++++-----------
 1 file changed, 111 insertions(+), 60 deletions(-)

diff --git a/src/couch/test/eunit/couch_js_tests.erl b/src/couch/test/eunit/couch_js_tests.erl
index ea28d4040..789b36321 100644
--- a/src/couch/test/eunit/couch_js_tests.erl
+++ b/src/couch/test/eunit/couch_js_tests.erl
@@ -22,6 +22,8 @@ couch_js_test_() ->
             fun test_util:stop_couch/1,
             [
                 fun should_create_sandbox/0,
+                fun should_reset_properly/0,
+                fun should_freeze_doc_object/0,
                 fun should_roundtrip_utf8/0,
                 fun should_roundtrip_modified_utf8/0,
                 fun should_replace_broken_utf16/0,
@@ -31,36 +33,80 @@ couch_js_test_() ->
         }
     }.
 
+%% erlfmt-ignore
 should_create_sandbox() ->
     % Try and detect whether we can see out of the
     % sandbox or not.
-    Src = <<
-        "function(doc) {\n"
-        "  try {\n"
-        "    emit(false, typeof(Couch.compile_function));\n"
-        "  } catch (e) {\n"
-        "    emit(true, e.message);\n"
-        "  }\n"
-        "}\n"
-    >>,
+    Src = <<"
+        function(doc) {
+            try {
+                emit(false, typeof(Couch.compile_function));
+            } catch (e) {
+                emit(true, e.message);
+            }
+        }
+    ">>,
+    Proc = couch_query_servers:get_os_process(<<"javascript">>),
+    true = couch_query_servers:proc_prompt(Proc, [<<"add_fun">>, Src]),
+    Result = couch_query_servers:proc_prompt(Proc, [<<"map_doc">>, {[]}]),
+    ?assertMatch([[[true, <<_/binary>>]]], Result),
+    [[[true, ErrMsg]]] = Result,
+    ?assertNotEqual([], binary:matches(ErrMsg, <<"not defined">>)),
+    couch_query_servers:ret_os_process(Proc).
+
+%% erlfmt-ignore
+should_reset_properly() ->
+    Src = <<"
+        function(doc) {
+            var a = [0,1,2];
+            emit(a.indexOf(0), Object.foo);
+            Object.foo = 43;
+            [].constructor.prototype.indexOf = function(x) {return 42;};
+        }
+    ">>,
     Proc = couch_query_servers:get_os_process(<<"javascript">>),
     true = couch_query_servers:proc_prompt(Proc, [<<"add_fun">>, Src]),
-    Result = couch_query_servers:proc_prompt(Proc, [<<"map_doc">>, <<"{}">>]),
-    ?assertEqual([[[true, <<"Couch is not defined">>]]], Result).
+    Doc = {[]},
+    Result1 = couch_query_servers:proc_prompt(Proc, [<<"map_doc">>, Doc]),
+    ?assertEqual([[[0, null]]], Result1),
+    Result2 = couch_query_servers:proc_prompt(Proc, [<<"map_doc">>, Doc]),
+    ?assertEqual([[[42, 43]]], Result2),
+    true = couch_query_servers:proc_prompt(Proc, [<<"reset">>]),
+    true = couch_query_servers:proc_prompt(Proc, [<<"add_fun">>, Src]),
+    Result3 = couch_query_servers:proc_prompt(Proc, [<<"map_doc">>, Doc]),
+    ?assertEqual([[[0, null]]], Result3),
+    couch_query_servers:ret_os_process(Proc).
 
+%% erlfmt-ignore
+should_freeze_doc_object() ->
+    Src = <<"
+        function(doc) {
+            emit(doc.foo, doc.bar);
+            doc.foo = 1042;
+            doc.bar = 1043;
+            emit(doc.foo, doc.bar);
+        }
+    ">>,
+    Proc = couch_query_servers:get_os_process(<<"javascript">>),
+    true = couch_query_servers:proc_prompt(Proc, [<<"add_fun">>, Src]),
+    Doc = {[{<<"bar">>, 1041}]},
+    Result1 = couch_query_servers:proc_prompt(Proc, [<<"map_doc">>, Doc]),
+    ?assertEqual([[[null, 1041], [null, 1041]]], Result1),
+    Result2 = couch_query_servers:proc_prompt(Proc, [<<"map_doc">>, Doc]),
+    ?assertEqual([[[null, 1041], [null, 1041]]], Result2),
+    couch_query_servers:ret_os_process(Proc).
+
+%% erlfmt-ignore
 should_roundtrip_utf8() ->
     % Try round tripping UTF-8 both directions through
     % couchjs. These tests use hex encoded values of
     % Ä (C384) and Ü (C39C) so as to avoid odd editor/Erlang encoding
     % strangeness.
     Src = <<
-        "function(doc) {\n"
-        "  emit(doc.value, \"",
-        16#C3,
-        16#9C,
-        "\");\n"
-        "}\n"
-    >>,
+        "function(doc) {
+          emit(doc.value, \"", 16#C3,  16#9C, "\");
+        }
+    ">>,
     Proc = couch_query_servers:get_os_process(<<"javascript">>),
     true = couch_query_servers:proc_prompt(Proc, [<<"add_fun">>, Src]),
     Doc =
@@ -68,18 +114,17 @@ should_roundtrip_utf8() ->
             {<<"value">>, <<16#C3, 16#84>>}
         ]},
     Result = couch_query_servers:proc_prompt(Proc, [<<"map_doc">>, Doc]),
-    ?assertEqual([[[<<16#C3, 16#84>>, <<16#C3, 16#9C>>]]], Result).
+    ?assertEqual([[[<<16#C3, 16#84>>, <<16#C3, 16#9C>>]]], Result),
+    couch_query_servers:ret_os_process(Proc).
 
+%% erlfmt-ignore
 should_roundtrip_modified_utf8() ->
     % Mimicking the test case from the mailing list
-    Src = <<
-        "function(doc) {\n"
-        "  emit(doc.value.toLowerCase(), \"",
-        16#C3,
-        16#9C,
-        "\");\n"
-        "}\n"
-    >>,
+    Src = <<"
+        function(doc) {
+          emit(doc.value.toLowerCase(), \"", 16#C3, 16#9C, "\");
+        }
+    ">>,
     Proc = couch_query_servers:get_os_process(<<"javascript">>),
     true = couch_query_servers:proc_prompt(Proc, [<<"add_fun">>, Src]),
     Doc =
@@ -87,16 +132,18 @@ should_roundtrip_modified_utf8() ->
             {<<"value">>, <<16#C3, 16#84>>}
         ]},
     Result = couch_query_servers:proc_prompt(Proc, [<<"map_doc">>, Doc]),
-    ?assertEqual([[[<<16#C3, 16#A4>>, <<16#C3, 16#9C>>]]], Result).
+    ?assertEqual([[[<<16#C3, 16#A4>>, <<16#C3, 16#9C>>]]], Result),
+    couch_query_servers:ret_os_process(Proc).
 
+%% erlfmt-ignore
 should_replace_broken_utf16() ->
     % This test reverse the surrogate pair of
     % the Boom emoji U+1F4A5
-    Src = <<
-        "function(doc) {\n"
-        "  emit(doc.value.split(\"\").reverse().join(\"\"), 1);\n"
-        "}\n"
-    >>,
+    Src = <<"
+        function(doc) {
+            emit(doc.value.split(\"\").reverse().join(\"\"), 1);
+        }
+    ">>,
     Proc = couch_query_servers:get_os_process(<<"javascript">>),
     true = couch_query_servers:proc_prompt(Proc, [<<"add_fun">>, Src]),
     Doc =
@@ -107,8 +154,10 @@ should_replace_broken_utf16() ->
     % Invalid UTF-8 gets replaced with the 16#FFFD replacement
     % marker
     Markers = list_to_binary(xmerl_ucs:to_utf8([16#FFFD, 16#FFFD])),
-    ?assertEqual([[[Markers, 1]]], Result).
+    ?assertEqual([[[Markers, 1]]], Result),
+    couch_query_servers:ret_os_process(Proc).
 
+%% erlfmt-ignore
 should_allow_js_string_mutations() ->
     % This binary corresponds to this string: мама мыла раму
     % Which I'm told translates to: "mom was washing the frame"
@@ -142,21 +191,21 @@ should_allow_js_string_mutations() ->
     >>,
     Mom = <<16#D0, 16#BC, 16#D0, 16#B0, 16#D0, 16#BC, 16#D0, 16#B0>>,
     Washed = <<16#D0, 16#BC, 16#D1, 16#8B, 16#D0, 16#BB, 16#D0, 16#B0>>,
-    Src1 = <<
-        "function(doc) {\n"
-        "  emit(\"length\", doc.value.length);\n"
-        "}\n"
-    >>,
-    Src2 = <<
-        "function(doc) {\n"
-        "  emit(\"substring\", doc.value.substring(5, 9));\n"
-        "}\n"
-    >>,
-    Src3 = <<
-        "function(doc) {\n"
-        "  emit(\"slice\", doc.value.slice(0, 4));\n"
-        "}\n"
-    >>,
+    Src1 = <<"
+        function(doc) {
+          emit(\"length\", doc.value.length);
+        }
+    ">>,
+    Src2 = <<"
+        function(doc) {
+          emit(\"substring\", doc.value.substring(5, 9));
+        }
+    ">>,
+    Src3 = <<"
+        function(doc) {
+          emit(\"slice\", doc.value.slice(0, 4));
+        }
+    ">>,
     Proc = couch_query_servers:get_os_process(<<"javascript">>),
     true = couch_query_servers:proc_prompt(Proc, [<<"add_fun">>, Src1]),
     true = couch_query_servers:proc_prompt(Proc, [<<"add_fun">>, Src2]),
@@ -168,19 +217,21 @@ should_allow_js_string_mutations() ->
         [[<<"substring">>, Washed]],
         [[<<"slice">>, Mom]]
     ],
-    ?assertEqual(Expect, Result).
+    ?assertEqual(Expect, Result),
+    couch_query_servers:ret_os_process(Proc).
 
+%% erlfmt-ignore
 should_exit_on_oom() ->
-    Src = <<
-        "var state = [];\n"
-        "function(doc) {\n"
-        "  var val = \"0123456789ABCDEF\";\n"
-        "  for(var i = 0; i < 665535; i++) {\n"
-        "    state.push([val, val]);\n"
-        "    emit(null, null);\n"
-        "  }\n"
-        "}\n"
-    >>,
+    Src = <<"
+        var state = [];
+        function(doc) {
+            var val = \"0123456789ABCDEF\";
+            for(var i = 0; i < 665535; i++) {
+                state.push([val, val]);
+                emit(null, null);
+             }
+        }
+    ">>,
     Proc = couch_query_servers:get_os_process(<<"javascript">>),
     true = couch_query_servers:proc_prompt(Proc, [<<"add_fun">>, Src]),
     trigger_oom(Proc).