You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@spot.apache.org by ra...@apache.org on 2017/05/30 18:30:40 UTC

[3/5] incubator-spot git commit: class ProxySuspiciousConnectsModel: We are moving away from quantiles which are computationally expensive and data dependent. In this new version we got rid of the val timeCuts which computed quantiles. We also modified v

class ProxySuspiciousConnectsModel: We are moving away from quantiles which are computationally expensive and data dependent. In this new version we got rid of the val timeCuts which computed quantiles. We also modified val entropyCuts to have a fixed number of buckets and therefore quantiles are no longer computed. All references to timeCuts and agentCuts were removed.

object ProxyWordCreation: We got rid of the timeCuts and agentCuts references because they are no longer computed in quantiles. entropy cuts is still passed as a parameter but the buckets are fixed. A new feature was added to the word formation which considers the URI length in exponential cutoffs.

object ExponentialCutoffs: This object has a method which answers the question: To what power must base be raise in order to yield x. It offers the flexibility to change the base.

object Quantiles: No changes were made to this object.

object TimeUtilities: A mew method getTimeAsHour was added in order to extract only the hour element of the string time.

class ExponentialCutoffsTest: A unit test was added to test this function

class TimeUtilitiesTest: Unit tests were added to test the methods of TimeUtilities

class QuantilesTest: No changes wer made to this test.

UPDATE1: Made the changes suggested by NathanSegerlind

Added the unit test called: ProxyWordCreationTest.scala to test the functionality of ProxyWordCreation

UPDATE2: Made the changes suggested by NathanSegerlind on 05/25/2017
Changed 1.0 / 0 to Double.PositiveInfinity
Changed object ExponentialCutoffs to MathUtils
Changed the name of the val records (logs) in ProxyWordCreationTest to be more informative
Flattened the records (logs)


Project: http://git-wip-us.apache.org/repos/asf/incubator-spot/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-spot/commit/7d063ae2
Tree: http://git-wip-us.apache.org/repos/asf/incubator-spot/tree/7d063ae2
Diff: http://git-wip-us.apache.org/repos/asf/incubator-spot/diff/7d063ae2

Branch: refs/heads/master
Commit: 7d063ae2390465619f028ad42536b73bc31c991e
Parents: 1fa798f
Author: lujangus <gu...@intel.com>
Authored: Thu May 25 16:22:45 2017 -0500
Committer: lujangus <gu...@intel.com>
Committed: Thu May 25 16:22:45 2017 -0500

----------------------------------------------------------------------
 .../proxy/ProxySuspiciousConnectsModel.scala    |   2 +-
 .../apache/spot/proxy/ProxyWordCreation.scala   |   4 +-
 .../spot/utilities/ExponentialCutoffs.scala     |  33 ---
 .../org/apache/spot/utilities/MathUtils.scala   |  31 +++
 .../spot/proxy/ProxyWordCreationTest.scala      | 263 +++++--------------
 .../spot/utilities/ExponentialCutoffsTest.scala |  44 ----
 .../apache/spot/utilities/MathUtilsTest.scala   |  40 +++
 7 files changed, 136 insertions(+), 281 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-spot/blob/7d063ae2/spot-ml/src/main/scala/org/apache/spot/proxy/ProxySuspiciousConnectsModel.scala
----------------------------------------------------------------------
diff --git a/spot-ml/src/main/scala/org/apache/spot/proxy/ProxySuspiciousConnectsModel.scala b/spot-ml/src/main/scala/org/apache/spot/proxy/ProxySuspiciousConnectsModel.scala
index 6c5a5a3..78a8ba5 100644
--- a/spot-ml/src/main/scala/org/apache/spot/proxy/ProxySuspiciousConnectsModel.scala
+++ b/spot-ml/src/main/scala/org/apache/spot/proxy/ProxySuspiciousConnectsModel.scala
@@ -123,7 +123,7 @@ object ProxySuspiciousConnectsModel {
     val EntropyCuts = Array(0.0, 0.3, 0.6, 0.9, 1.2,
       1.5, 1.8, 2.1, 2.4, 2.7,
       3.0, 3.3, 3.6, 3.9, 4.2,
-      4.5, 4.8, 5.1, 5.4, 1.0 / 0)
+      4.5, 4.8, 5.1, 5.4, Double.PositiveInfinity)
 
     val agentToCount: Map[String, Long] =
       selectedRecords.select(UserAgent)

http://git-wip-us.apache.org/repos/asf/incubator-spot/blob/7d063ae2/spot-ml/src/main/scala/org/apache/spot/proxy/ProxyWordCreation.scala
----------------------------------------------------------------------
diff --git a/spot-ml/src/main/scala/org/apache/spot/proxy/ProxyWordCreation.scala b/spot-ml/src/main/scala/org/apache/spot/proxy/ProxyWordCreation.scala
index 5030d1b..3d59c36 100644
--- a/spot-ml/src/main/scala/org/apache/spot/proxy/ProxyWordCreation.scala
+++ b/spot-ml/src/main/scala/org/apache/spot/proxy/ProxyWordCreation.scala
@@ -63,9 +63,9 @@ object ProxyWordCreation {
         // Just the top level content type for now
         if (contentType.split('/').length > 0) contentType.split('/')(0) else "unknown_content_type",
         // Exponential cutoffs base 2
-        ExponentialCutoffs.logBaseXInt(agentCounts.value(userAgent), 2),
+        MathUtils.logBaseXInt(agentCounts.value(userAgent), 2),
         // Exponential cutoffs base 2
-        ExponentialCutoffs.logBaseXInt(uri.length(), 2),
+        MathUtils.logBaseXInt(uri.length(), 2),
         // Response code using all 3 digits
         if (responseCode != null) responseCode else "unknown_response_code").mkString("_")
     } match {

http://git-wip-us.apache.org/repos/asf/incubator-spot/blob/7d063ae2/spot-ml/src/main/scala/org/apache/spot/utilities/ExponentialCutoffs.scala
----------------------------------------------------------------------
diff --git a/spot-ml/src/main/scala/org/apache/spot/utilities/ExponentialCutoffs.scala b/spot-ml/src/main/scala/org/apache/spot/utilities/ExponentialCutoffs.scala
deleted file mode 100644
index 9ddeee8..0000000
--- a/spot-ml/src/main/scala/org/apache/spot/utilities/ExponentialCutoffs.scala
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.spot.utilities
-
-import scala.math.log10
-
-
-object ExponentialCutoffs {
-  /**
-    * Answers the question "To what power must "base" be raised, in order to yield "x"?  https://en.wikipedia.org/wiki/Logarithm
-    *
-    * @param x    This is a Double which is the result of the formula: base to the power of y = x
-    * @param base This is the base of the number we are trying to find
-    * @return A rounded down integer of y
-    */
-  def logBaseXInt(x: Double, base: Int): Int = if (x == 0) 0 else (log10(x) / log10(base)).toInt
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-spot/blob/7d063ae2/spot-ml/src/main/scala/org/apache/spot/utilities/MathUtils.scala
----------------------------------------------------------------------
diff --git a/spot-ml/src/main/scala/org/apache/spot/utilities/MathUtils.scala b/spot-ml/src/main/scala/org/apache/spot/utilities/MathUtils.scala
new file mode 100644
index 0000000..e5f30b7
--- /dev/null
+++ b/spot-ml/src/main/scala/org/apache/spot/utilities/MathUtils.scala
@@ -0,0 +1,31 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.spot.utilities
+
+import scala.math.log10
+
+object MathUtils {
+  /**
+    * Answers the question "To what power must "base" be raised, in order to yield "x"?  https://en.wikipedia.org/wiki/Logarithm
+    *
+    * @param x    This is a Double which is the result of the formula: base to the power of y = x
+    * @param base This is the base of the number we are trying to find
+    * @return y rounded down to an integer
+    */
+  def logBaseXInt(x: Double, base: Int): Int = if (x == 0) 0 else (log10(x) / log10(base)).toInt
+}

http://git-wip-us.apache.org/repos/asf/incubator-spot/blob/7d063ae2/spot-ml/src/test/scala/org/apache/spot/proxy/ProxyWordCreationTest.scala
----------------------------------------------------------------------
diff --git a/spot-ml/src/test/scala/org/apache/spot/proxy/ProxyWordCreationTest.scala b/spot-ml/src/test/scala/org/apache/spot/proxy/ProxyWordCreationTest.scala
index eded0be..d1bc9ae 100644
--- a/spot-ml/src/test/scala/org/apache/spot/proxy/ProxyWordCreationTest.scala
+++ b/spot-ml/src/test/scala/org/apache/spot/proxy/ProxyWordCreationTest.scala
@@ -1,5 +1,21 @@
-package org.apache.spot.proxy
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
 
+package org.apache.spot.proxy
 
 import org.apache.log4j.{Level, LogManager}
 import org.apache.spot.SuspiciousConnectsArgumentParser.SuspiciousConnectsConfig
@@ -7,7 +23,6 @@ import org.apache.spot.proxy.ProxySchema.Word
 import org.apache.spot.testutils.TestingSparkContextFlatSpec
 import org.scalatest.Matchers
 
-
 class ProxyWordCreationTest extends TestingSparkContextFlatSpec with Matchers {
 
   val testConfigProxy = SuspiciousConnectsConfig(analysis = "proxy",
@@ -24,7 +39,7 @@ class ProxyWordCreationTest extends TestingSparkContextFlatSpec with Matchers {
     ldaAlpha = 1.02,
     ldaBeta = 1.001)
 
-  "proxy word creation" should "return the correct word given the rules to form the word" in {
+  "proxy word creation" should "return the correct word given the set of rules to form the word" in {
 
     val logger = LogManager.getLogger("ProxyWordCreation")
     logger.setLevel(Level.WARN)
@@ -50,220 +65,67 @@ class ProxyWordCreationTest extends TestingSparkContextFlatSpec with Matchers {
     // 18 csbytes:Int,
     // 19 fulluri:String)     <- currently used for feature creation
 
-    val record1 = ProxyInput(
-      "2016-10-03",
-      "00:57:36",
-      "127.0.0.1",
-      "intel.com",
-      "PUT",
-      "Mozilla/5.0",
-      "text/plain",
-      230,
-      "-",
-      "Technology/Internet",
-      "http://www.spoonflower.com/tags/color",
-      "202",
-      80,
-      "/sites/c37i4q22szvir8ga3m8mtxaft7gwnm5fio8hfxo35mu81absi1/carts/4b3a313d-50f6-4117-8ffd-4e804fd354ef/fiddle",
-      "-",
-      "127.0.0.1",
-      338,
-      647,
-      "ab") //entropy = 1.0
-
-    val record2 = ProxyInput(
-      "2016-10-03",
-      "01:57:36",
-      "127.0.0.1",
-      "maw.bronto.com",
-      "PUT",
-      "Safari/537.36",
-      "image",
-      230,
-      "-",
-      "Technology/Internet",
-      "http://www.spoonflower.com/tags/color",
-      "202",
-      80,
+    val noAlexaPutLoEntroTextRareAgentShortUri202 = ProxyInput("2016-10-03", "00:57:36", "127.0.0.1", "intel.com", "PUT",
+      "Mozilla/5.0", "text/plain", 230, "-", "Technology/Internet", "http://www.spoonflower.com/tags/color", "202", 80,
       "/sites/c37i4q22szvir8ga3m8mtxaft7gwnm5fio8hfxo35mu81absi1/carts/4b3a313d-50f6-4117-8ffd-4e804fd354ef/fiddle",
-      "-",
-      "127.0.0.1",
-      338,
-      647,
-      "abc") //entropy = 1.5849625007211559
+      "-", "127.0.0.1", 338, 647, "ab")
 
-    val record3 = ProxyInput(
-      "2016-10-03",
-      "02:57:36",
-      "127.0.0.1",
-      "maw.bronto.com",
-      "PUT",
-      "Safari/537.36",
-      "image",
-      230,
-      "-",
-      "Technology/Internet",
-      "http://www.spoonflower.com/tags/color",
-      "304",
-      80,
+    val AlexaPutMidEntroImagePopularAgentShortUri202 = ProxyInput("2016-10-03", "01:57:36", "127.0.0.1", "maw.bronto.com",
+      "PUT", "Safari/537.36", "image", 230, "-", "Technology/Internet", "http://www.spoonflower.com/tags/color", "202", 80,
       "/sites/c37i4q22szvir8ga3m8mtxaft7gwnm5fio8hfxo35mu81absi1/carts/4b3a313d-50f6-4117-8ffd-4e804fd354ef/fiddle",
-      "-",
-      "127.0.0.1",
-      338,
-      647,
-      "abcd") //entropy = 2.0
+      "-", "127.0.0.1", 338, 647, "abc")
 
-    val record4 = ProxyInput(
-      "2016-10-03",
-      "03:57:36",
-      "127.0.0.1",
-      "maw.bronto.com",
-      "PUT",
-      "Safari/537.36",
-      "binary",
-      230,
-      "-",
-      "Technology/Internet",
-      "http://www.spoonflower.com/tags/color",
-      "304",
-      80,
+    val AlexaPutMidEntroImagePopularAgentShortUri304 = ProxyInput("2016-10-03", "02:57:36", "127.0.0.1", "maw.bronto.com",
+      "PUT", "Safari/537.36", "image", 230, "-", "Technology/Internet", "http://www.spoonflower.com/tags/color", "304", 80,
       "/sites/c37i4q22szvir8ga3m8mtxaft7gwnm5fio8hfxo35mu81absi1/carts/4b3a313d-50f6-4117-8ffd-4e804fd354ef/fiddle",
-      "-",
-      "127.0.0.1",
-      338,
-      647,
-      "abcde") // entropy = 2.321928094887362
+      "-", "127.0.0.1", 338, 647, "abcd")
 
-    val record5 = ProxyInput(
-      "2016-10-03",
-      "10:57:36",
-      "127.0.0.1",
-      "maw.bronto.com",
-      "PUT",
-      "Safari/537.36",
-      "binary",
-      230,
-      "-",
-      "Technology/Internet",
-      "http://www.spoonflower.com/tags/color",
-      "206",
-      80,
+    val AlexaPutMidEntroBinaryPopularAgentShortUri304 = ProxyInput("2016-10-03", "03:57:36", "127.0.0.1", "maw.bronto.com",
+      "PUT", "Safari/537.36", "binary", 230, "-", "Technology/Internet", "http://www.spoonflower.com/tags/color", "304", 80,
       "/sites/c37i4q22szvir8ga3m8mtxaft7gwnm5fio8hfxo35mu81absi1/carts/4b3a313d-50f6-4117-8ffd-4e804fd354ef/fiddle",
-      "-",
-      "127.0.0.1",
-      338,
-      647,
-      "abcdef") //entropy = 2.584962500721155
+      "-", "127.0.0.1", 338, 647, "abcde")
 
-    val record6 = ProxyInput(
-      "2016-10-03",
-      "11:57:36",
-      "127.0.0.1",
-      "maw.bronto.com",
-      "GET",
-      "Safari/537.36",
-      "binary",
-      230,
-      "-",
-      "Technology/Internet",
-      "http://www.spoonflower.com/tags/color",
-      "206",
-      80,
+    val AlexaPutMidEntroBinaryPopularAgentShortUri206 = ProxyInput("2016-10-03", "10:57:36", "127.0.0.1", "maw.bronto.com",
+      "PUT", "Safari/537.36", "binary", 230, "-", "Technology/Internet", "http://www.spoonflower.com/tags/color", "206", 80,
       "/sites/c37i4q22szvir8ga3m8mtxaft7gwnm5fio8hfxo35mu81absi1/carts/4b3a313d-50f6-4117-8ffd-4e804fd354ef/fiddle",
-      "-",
-      "127.0.0.1",
-      338,
-      647,
-      "abcdefghijklmnopqrstuvwxyz") //4.70043971814109
+      "-", "127.0.0.1", 338, 647, "abcdef")
 
-    val record7 = ProxyInput(
-      "2016-10-03",
-      "13:57:36",
-      "127.0.0.1",
-      "maw.bronto.com",
-      "GET",
-      "Safari/537.36",
-      "text/plain",
-      230,
-      "-",
-      "Technology/Internet",
-      "http://www.spoonflower.com/tags/color",
-      "200",
-      80,
+    val AlexaGetHiEntroBinaryPopularAgentShortUri206 = ProxyInput("2016-10-03", "11:57:36", "127.0.0.1", "maw.bronto.com",
+      "GET", "Safari/537.36", "binary", 230, "-", "Technology/Internet", "http://www.spoonflower.com/tags/color", "206", 80,
       "/sites/c37i4q22szvir8ga3m8mtxaft7gwnm5fio8hfxo35mu81absi1/carts/4b3a313d-50f6-4117-8ffd-4e804fd354ef/fiddle",
-      "-",
-      "127.0.0.1",
-      338,
-      647,
-      "aaa") //entropy = 0.0
+      "-", "127.0.0.1", 338, 647, "abcdefghijklmnopqrstuvwxyz")
 
-    val record8 = ProxyInput(
-      "2016-10-03",
-      "14:57:36",
-      "127.0.0.1",
-      "maw.bronto.com",
-      "GET",
-      "Safari/537.36",
-      "text/plain",
-      230,
-      "-",
-      "Technology/Internet",
-      "http://www.spoonflower.com/tags/color",
-      "200",
-      80,
+    val AlexaGetZeroEntroTextPopularAgentShortUri200 = ProxyInput("2016-10-03", "13:57:36", "127.0.0.1", "maw.bronto.com",
+      "GET", "Safari/537.36", "text/plain", 230, "-", "Technology/Internet", "http://www.spoonflower.com/tags/color", "200", 80,
       "/sites/c37i4q22szvir8ga3m8mtxaft7gwnm5fio8hfxo35mu81absi1/carts/4b3a313d-50f6-4117-8ffd-4e804fd354ef/fiddle",
-      "-",
-      "127.0.0.1",
-      338,
-      647,
-      "aaabbb") //entropy 1.0
+      "-", "127.0.0.1", 338, 647, "aaa")
 
-    val record9 = ProxyInput(
-      "2016-10-03",
-      "22:57:36",
-      "127.0.0.1",
-      "maw.bronto.com",
-      "GET",
-      "Safari/537.36",
-      "text/plain",
-      230,
-      "-",
-      "Technology/Internet",
-      "http://www.spoonflower.com/tags/color",
-      "302",
-      80,
+    val AlexaGetLoEntroTextPopularAgentShortUri200 = ProxyInput("2016-10-03", "14:57:36", "127.0.0.1", "maw.bronto.com",
+      "GET", "Safari/537.36", "text/plain", 230, "-", "Technology/Internet", "http://www.spoonflower.com/tags/color", "200", 80,
       "/sites/c37i4q22szvir8ga3m8mtxaft7gwnm5fio8hfxo35mu81absi1/carts/4b3a313d-50f6-4117-8ffd-4e804fd354ef/fiddle",
-      "-",
-      "127.0.0.1",
-      338,
-      647,
-      "aaaaaaaaaaabbbbbbbbbbbccccccccccc") //entropy = 1.5849625007211559
+      "-", "127.0.0.1", 338, 647, "aaabbb")
 
-    val record10 = ProxyInput(
-      "2016-10-03",
-      "23:57:36",
-      "127.0.0.1",
-      "maw.bronto.com",
-      "GET",
-      "Safari/537.36",
-      "text/plain",
-      230,
-      "-",
-      "Technology/Internet",
-      "http://www.spoonflower.com/tags/color",
-      "302",
-      80,
+    val AlexaGetMidEntroTextPopularAgentMidUri302 = ProxyInput("2016-10-03", "22:57:36", "127.0.0.1", "maw.bronto.com",
+      "GET", "Safari/537.36", "text/plain", 230, "-", "Technology/Internet", "http://www.spoonflower.com/tags/color", "302", 80,
       "/sites/c37i4q22szvir8ga3m8mtxaft7gwnm5fio8hfxo35mu81absi1/carts/4b3a313d-50f6-4117-8ffd-4e804fd354ef/fiddle",
-      "-",
-      "127.0.0.1",
-      338,
-      647,
-      "maw.bronto.com/sites/c37i4q22szvir8ga3m8mtxaft7gwnm5fio8hfxo35mu81absi1/carts/4b3a313d-50f6-4117-8ffd" +
-        "-4e804fd354ef/fiddle") // entropy = 4.832854333602748
-
-
-    val data = sqlContext.createDataFrame(Seq(record1, record2, record3, record4, record5, record6, record7, record8,
-      record9, record10))
+      "-", "127.0.0.1", 338, 647, "aaaaaaaaaaabbbbbbbbbbbccccccccccc")
+
+    val AlexaGetHiEntroTextPopularAgentLargeUri302 = ProxyInput("2016-10-03", "23:57:36", "127.0.0.1", "maw.bronto.com",
+      "GET", "Safari/537.36", "text/plain", 230, "-", "Technology/Internet", "http://www.spoonflower.com/tags/color", "302",
+      80, "/sites/c37i4q22szvir8ga3m8mtxaft7gwnm5fio8hfxo35mu81absi1/carts/4b3a313d-50f6-4117-8ffd-4e804fd354ef/fiddle",
+      "-", "127.0.0.1", 338, 647, "maw.bronto.com/sites/c37i4q22szvir8ga3m8mtxaft7gwnm5fio8hfxo35mu81absi1/carts" +
+        "/4b3a313d-50f6-4117-8ffd-4e804fd354ef/fiddle")
+
+    val data = sqlContext.createDataFrame(Seq(noAlexaPutLoEntroTextRareAgentShortUri202,
+      AlexaPutMidEntroImagePopularAgentShortUri202,
+      AlexaPutMidEntroImagePopularAgentShortUri304,
+      AlexaPutMidEntroBinaryPopularAgentShortUri304,
+      AlexaPutMidEntroBinaryPopularAgentShortUri206,
+      AlexaGetHiEntroBinaryPopularAgentShortUri206,
+      AlexaGetZeroEntroTextPopularAgentShortUri200,
+      AlexaGetLoEntroTextPopularAgentShortUri200,
+      AlexaGetMidEntroTextPopularAgentMidUri302,
+      AlexaGetHiEntroTextPopularAgentLargeUri302))
 
     val scoredData = ProxySuspiciousConnectsAnalysis.detectProxyAnomalies(data, testConfigProxy,
       sparkContext,
@@ -282,6 +144,5 @@ class ProxyWordCreationTest extends TestingSparkContextFlatSpec with Matchers {
     words(7) shouldBe "1_14_GET_4_text_3_2_200"
     words(8) shouldBe "1_22_GET_6_text_3_5_302"
     words(9) shouldBe "1_23_GET_17_text_3_6_302"
-
   }
 }

http://git-wip-us.apache.org/repos/asf/incubator-spot/blob/7d063ae2/spot-ml/src/test/scala/org/apache/spot/utilities/ExponentialCutoffsTest.scala
----------------------------------------------------------------------
diff --git a/spot-ml/src/test/scala/org/apache/spot/utilities/ExponentialCutoffsTest.scala b/spot-ml/src/test/scala/org/apache/spot/utilities/ExponentialCutoffsTest.scala
deleted file mode 100644
index e1176a8..0000000
--- a/spot-ml/src/test/scala/org/apache/spot/utilities/ExponentialCutoffsTest.scala
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-
-package org.apache.spot.utilities
-
-import org.apache.spot.testutils.TestingSparkContextFlatSpec
-import org.scalatest.Matchers
-
-/**
-  * Created by galujanm on 5/17/17.
-  */
-class ExponentialCutoffsTest extends TestingSparkContextFlatSpec with Matchers {
-
-  "logBaseXInt" should "return the power in which the base is raised, in order to yield x rounded down to the nearest integer" in {
-
-    val power1 = ExponentialCutoffs.logBaseXInt(4.0, 2)
-    val power2 = ExponentialCutoffs.logBaseXInt(8.0, 2)
-    val power3 = ExponentialCutoffs.logBaseXInt(1.9, 2)
-    val power4 = ExponentialCutoffs.logBaseXInt(9.5, 3)
-
-    power1 shouldBe 2
-    power2 shouldBe 3
-    power3 shouldBe 0
-    power4 shouldBe 2
-
-
-  }
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-spot/blob/7d063ae2/spot-ml/src/test/scala/org/apache/spot/utilities/MathUtilsTest.scala
----------------------------------------------------------------------
diff --git a/spot-ml/src/test/scala/org/apache/spot/utilities/MathUtilsTest.scala b/spot-ml/src/test/scala/org/apache/spot/utilities/MathUtilsTest.scala
new file mode 100644
index 0000000..043f3f3
--- /dev/null
+++ b/spot-ml/src/test/scala/org/apache/spot/utilities/MathUtilsTest.scala
@@ -0,0 +1,40 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.spot.utilities
+
+import org.apache.spot.testutils.TestingSparkContextFlatSpec
+import org.scalatest.Matchers
+
+
+class MathUtilsTest extends TestingSparkContextFlatSpec with Matchers {
+
+  "logBaseXInt" should "return the power in which the base is raised, in order to yield x rounded down to the nearest integer" in {
+
+    val power1 = MathUtils.logBaseXInt(4.0, 2)
+    val power2 = MathUtils.logBaseXInt(8.0, 2)
+    val power3 = MathUtils.logBaseXInt(1.9, 2)
+    val power4 = MathUtils.logBaseXInt(9.5, 3)
+
+    power1 shouldBe 2
+    power2 shouldBe 3
+    power3 shouldBe 0
+    power4 shouldBe 2
+
+
+  }
+}