<commit_before>(ns org.zalando.stups.friboo.system.audit-log-test
  (:require [clojure.test :refer :all]
            [org.zalando.stups.friboo.system.audit-log :refer :all]
            [amazonica.aws.s3 :as s3]
            [clj-time.format :as tf]
            [overtone.at-at :as at]))

(deftest test-add-logs-to-empty-list
  (let [logs (ref [])
        new-logs ["foo" "bar"]]
    (add-logs logs new-logs)
    (is (= @logs ["foo" "bar"]))))

(deftest test-add-logs-to-existing-ones
  (let [logs (ref ["bla"])
        new-logs ["foo" "bar"]]
    (add-logs logs new-logs)
    (is (= @logs ["bla" "foo" "bar"]))))

(deftest test-add-no-logs-to-existing-ones
  (let [logs (ref ["bla"])
        new-logs []]
    (add-logs logs new-logs)
    (is (= @logs ["bla"]))))

(deftest test-empty-empty-logs
  (let [logs (ref [])
        previous-logs (empty-logs logs)]
    (is (empty? @logs))
    (is (empty? previous-logs))))

(deftest test-empty-logs
  (let [logs (ref ["foo" "bar"])
        previous-logs (empty-logs logs)]
    (is (empty? @logs))
    (is (= ["foo" "bar"] previous-logs))))

(deftest test-is-modifying
  (let [methods [:post :put :patch :delete]]
    (doseq [method methods]
      (is (is-modifying? {:request-method method})))))

(deftest test-is-non-modifying
  (let [methods [:get :head :options]]
    (doseq [method methods]
      (is (not (is-modifying? {:request-method method}))))))

(deftest test-collect-audit-logs
  (let [dummy-response {:status 200 :body "foobar"}
        dummy-request {:swagger        "will be erased"
                       :configuration  "will be erased"
                       :body           "will be erased"
                       :tokeninfo      {"access_token" "will be erased"
                                        "uid"          "testuser"}
                       :headers        {"authorization" "will be erased"
                                        "content-type"  "application/json"}
                       :parameters     {:foo "bar"}
                       :request-method :post}
        next-handler (constantly dummy-response)
        logs (ref [])
        handler-fn (collect-audit-logs next-handler {:audit-logs logs})]
    (is (= dummy-response (handler-fn dummy-request)))
    (is (seq @logs))
    (let [line (first @logs)]
      (is (= (set (keys line)) #{:tokeninfo :headers :parameters :request-method :logged-on}))
      (is (= (:tokeninfo line) {"uid" "testuser"}))
      (is (= (:headers line) {"content-type" "application/json"})))))

(deftest test-collect-no-audit-logs-when-no-success1
  (let [dummy-response {:status 400 :body "foobar"}
        dummy-request {:swagger        "will be erased"
                       :configuration  "will be erased"
                       :body           "will be erased"
                       :tokeninfo      {"access_token" "will be erased"
                                        "uid"          "testuser"}
                       :headers        {"authorization" "will be erased"
                                        "content-type"  "application/json"}
                       :parameters     {:foo "bar"}
                       :request-method :post}
        next-handler (constantly dummy-response)
        logs (ref [])
        handler-fn (collect-audit-logs next-handler {:audit-logs logs})]
    (is (= dummy-response (handler-fn dummy-request)))
    (is (empty? @logs))))

(deftest test-collect-no-audit-logs-when-no-success2
  (let [dummy-response {:status 100 :body "foobar"}
        dummy-request {:swagger        "will be erased"
                       :configuration  "will be erased"
                       :body           "will be erased"
                       :tokeninfo      {"access_token" "will be erased"
                                        "uid"          "testuser"}
                       :headers        {"authorization" "will be erased"
                                        "content-type"  "application/json"}
                       :parameters     {:foo "bar"}
                       :request-method :post}
        next-handler (constantly dummy-response)
        logs (ref [])
        handler-fn (collect-audit-logs next-handler {:audit-logs logs})]
    (is (= dummy-response (handler-fn dummy-request)))
    (is (empty? @logs))))


(deftest test-collect-no-audit-logs-when-not-modifying
  (let [dummy-response {:status 200 :body "foobar"}
        dummy-request {:swagger        "will be erased"
                       :configuration  "will be erased"
                       :body           "will be erased"
                       :tokeninfo      {"access_token" "will be erased"
                                        "uid"          "testuser"}
                       :headers        {"authorization" "will be erased"
                                        "content-type"  "application/json"}
                       :parameters     {:foo "bar"}
                       :request-method :get}
        next-handler (constantly dummy-response)
        logs (ref [])
        handler-fn (collect-audit-logs next-handler {:audit-logs logs})]
    (is (= dummy-response (handler-fn dummy-request)))
    (is (empty? @logs))))

(deftest test-collect-no-audit-logs-when-disabled
  (let [dummy-response {:status 200 :body "foobar"}
        dummy-request {:swagger        "will be erased"
                       :configuration  "will be erased"
                       :body           "will be erased"
                       :tokeninfo      {"access_token" "will be erased"
                                        "uid"          "testuser"}
                       :headers        {"authorization" "will be erased"
                                        "content-type"  "application/json"}
                       :parameters     {:foo "bar"}
                       :request-method :post}
        next-handler (constantly dummy-response)
        logs (ref [])
        handler-fn (collect-audit-logs next-handler {:audit-logs nil})]
    (is (= dummy-response (handler-fn dummy-request)))
    (is (empty? @logs))))

(defn track
  "Adds a tuple on call for an action."
  ([a action]
   (fn [& all-args]
     (swap! a conj {:key  action
                    :args (into [] all-args)}))))

(deftest test-store-audit-logs
  (let [calls (atom [])
        audit-logs (ref [{:foo "bar"} {:foo "baz"}])]
    (with-redefs [s3/put-object (track calls :s3-put)
                  audit-logs-file-formatter (tf/formatter "'test-file'")]
      (store-audit-logs! audit-logs "test-bucket")

      (is (= 1 (count @calls)))
      (let [args (apply hash-map (:args (first @calls)))]
        (is (= (:key args) "test-file"))
        (is (= (:bucket-name args) "test-bucket"))
        (is (= (get-in args [:metadata :content-length]) 27))
        (is (= (with-open [rdr (clojure.java.io/reader (:input-stream args))]
                 (reduce conj [] (line-seq rdr)))
               ["{\"foo\":\"bar\"}", "{\"foo\":\"baz\"}"]))
        (is (empty? @audit-logs))))))

(deftest test-store-empty-audit-logs
  (let [calls (atom [])
        audit-logs (ref [])]
    (with-redefs [s3/put-object (track calls :s3-put)
                  audit-logs-file-formatter (tf/formatter "'test-file'")]
      (store-audit-logs! audit-logs "test-bucket")

      (is (empty? @calls)))))

(deftest test-store-audit-logs-failed<commit_msg>audit log test case with InputStream<commit_after>(ns org.zalando.stups.friboo.system.audit-log-test
  (:require [clojure.test :refer :all]
            [org.zalando.stups.friboo.system.audit-log :refer :all]
            [amazonica.aws.s3 :as s3]
            [clj-time.format :as tf]
            [overtone.at-at :as at])
  (:import (java.io ByteArrayInputStream)))

(deftest test-add-logs-to-empty-list
  (let [logs (ref [])
        new-logs ["foo" "bar"]]
    (add-logs logs new-logs)
    (is (= @logs ["foo" "bar"]))))

(deftest test-add-logs-to-existing-ones
  (let [logs (ref ["bla"])
        new-logs ["foo" "bar"]]
    (add-logs logs new-logs)
    (is (= @logs ["bla" "foo" "bar"]))))

(deftest test-add-no-logs-to-existing-ones
  (let [logs (ref ["bla"])
        new-logs []]
    (add-logs logs new-logs)
    (is (= @logs ["bla"]))))

(deftest test-empty-empty-logs
  (let [logs (ref [])
        previous-logs (empty-logs logs)]
    (is (empty? @logs))
    (is (empty? previous-logs))))

(deftest test-empty-logs
  (let [logs (ref ["foo" "bar"])
        previous-logs (empty-logs logs)]
    (is (empty? @logs))
    (is (= ["foo" "bar"] previous-logs))))

(deftest test-is-modifying
  (let [methods [:post :put :patch :delete]]
    (doseq [method methods]
      (is (is-modifying? {:request-method method})))))

(deftest test-is-non-modifying
  (let [methods [:get :head :options]]
    (doseq [method methods]
      (is (not (is-modifying? {:request-method method}))))))

(deftest test-collect-audit-logs
  (let [dummy-response {:status 200 :body "foobar"}
        dummy-request {:swagger        "will be erased"
                       :configuration  "will be erased"
                       :body           "will be erased"
                       :tokeninfo      {"access_token" "will be erased"
                                        "uid"          "testuser"}
                       :headers        {"authorization" "will be erased"
                                        "content-type"  "application/json"}
                       :parameters     {:foo "bar"}
                       :request-method :post}
        next-handler (constantly dummy-response)
        logs (ref [])
        handler-fn (collect-audit-logs next-handler {:audit-logs logs})]
    (is (= dummy-response (handler-fn dummy-request)))
    (is (seq @logs))
    (let [line (first @logs)]
      (is (= (set (keys line)) #{:tokeninfo :headers :parameters :request-method :logged-on}))
      (is (= (:tokeninfo line) {"uid" "testuser"}))
      (is (= (:headers line) {"content-type" "application/json"})))))

(deftest test-collect-no-audit-logs-when-no-success1
  (let [dummy-response {:status 400 :body "foobar"}
        dummy-request {:swagger        "will be erased"
                       :configuration  "will be erased"
                       :body           "will be erased"
                       :tokeninfo      {"access_token" "will be erased"
                                        "uid"          "testuser"}
                       :headers        {"authorization" "will be erased"
                                        "content-type"  "application/json"}
                       :parameters     {:foo "bar"}
                       :request-method :post}
        next-handler (constantly dummy-response)
        logs (ref [])
        handler-fn (collect-audit-logs next-handler {:audit-logs logs})]
    (is (= dummy-response (handler-fn dummy-request)))
    (is (empty? @logs))))

(deftest test-collect-no-audit-logs-when-no-success2
  (let [dummy-response {:status 100 :body "foobar"}
        dummy-request {:swagger        "will be erased"
                       :configuration  "will be erased"
                       :body           "will be erased"
                       :tokeninfo      {"access_token" "will be erased"
                                        "uid"          "testuser"}
                       :headers        {"authorization" "will be erased"
                                        "content-type"  "application/json"}
                       :parameters     {:foo "bar"}
                       :request-method :post}
        next-handler (constantly dummy-response)
        logs (ref [])
        handler-fn (collect-audit-logs next-handler {:audit-logs logs})]
    (is (= dummy-response (handler-fn dummy-request)))
    (is (empty? @logs))))


(deftest test-collect-no-audit-logs-when-not-modifying
  (let [dummy-response {:status 200 :body "foobar"}
        dummy-request {:swagger        "will be erased"
                       :configuration  "will be erased"
                       :body           "will be erased"
                       :tokeninfo      {"access_token" "will be erased"
                                        "uid"          "testuser"}
                       :headers        {"authorization" "will be erased"
                                        "content-type"  "application/json"}
                       :parameters     {:foo "bar"}
                       :request-method :get}
        next-handler (constantly dummy-response)
        logs (ref [])
        handler-fn (collect-audit-logs next-handler {:audit-logs logs})]
    (is (= dummy-response (handler-fn dummy-request)))
    (is (empty? @logs))))

(deftest test-collect-no-audit-logs-when-disabled
  (let [dummy-response {:status 200 :body "foobar"}
        dummy-request {:swagger        "will be erased"
                       :configuration  "will be erased"
                       :body           "will be erased"
                       :tokeninfo      {"access_token" "will be erased"
                                        "uid"          "testuser"}
                       :headers        {"authorization" "will be erased"
                                        "content-type"  "application/json"}
                       :parameters     {:foo "bar"}
                       :request-method :post}
        next-handler (constantly dummy-response)
        logs (ref [])
        handler-fn (collect-audit-logs next-handler {:audit-logs nil})]
    (is (= dummy-response (handler-fn dummy-request)))
    (is (empty? @logs))))

(defn track
  "Adds a tuple on call for an action."
  ([a action]
   (fn [& all-args]
     (swap! a conj {:key  action
                    :args (into [] all-args)}))))

(deftest test-store-audit-logs
  (let [calls (atom [])
        audit-logs (ref [{:foo "bar"}
                         {:foo "baz"}
                         {:hello (ByteArrayInputStream. (.getBytes "this should not be visible"))}])]
    (with-redefs [s3/put-object (track calls :s3-put)
                  audit-logs-file-formatter (tf/formatter "'test-file'")]
      (store-audit-logs! audit-logs "test-bucket")

      (is (= 1 (count @calls)))
      (let [args (apply hash-map (:args (first @calls)))]
        (is (= (:key args) "test-file"))
        (is (= (:bucket-name args) "test-bucket"))
        (is (= (get-in args [:metadata :content-length]) 91))
        (is (= (with-open [rdr (clojure.java.io/reader (:input-stream args))]
                 (reduce conj [] (line-seq rdr)))
               ["{\"foo\":\"bar\"}", "{\"foo\":\"baz\"}", "{\"hello\":\"Some java.io.ByteArrayInputStream. Content omitted.\"}"]))
        (is (empty? @audit-logs))))))

(deftest test-store-empty-audit-logs
  (let [calls (atom [])
        audit-logs (ref [])]
    (with-redefs [s3/put-object (track calls :s3-put)
                  audit-logs-file-formatter (tf/formatter "'test-file'")]
      (store-audit-logs! audit-logs "test-bucket")

      (is (empty? @calls)))))

(deftest test-store-audit-logs-failed
{'fraction_non_alphanumeric': 0.14937286202964653, 'fraction_numerical': 0.0034878261452813736, 'mean_word_length': 1.6893939393939394, 'pattern_counts': {'":': 5, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 20, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3311394', 'n_tokens_mistral': 4562, 'n_tokens_neox': 4293, 'n_words': 1097}