Append Stopped animation notify list at Update Animation time
[platform/core/uifw/dali-core.git] / automated-tests / src / dali / utc-Dali-Animation.cpp
index 629d3e4..f360cbd 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -18,6 +18,7 @@
 #include <dali-test-suite-utils.h>
 #include <dali/devel-api/actors/actor-devel.h>
 #include <dali/devel-api/animation/animation-devel.h>
+#include <dali/devel-api/animation/key-frames-devel.h>
 #include <dali/public-api/dali-core.h>
 #include <stdlib.h>
 
@@ -2216,9 +2217,91 @@ int UtcDaliAnimationPlayP(void)
   END_TEST;
 }
 
+int UtcDaliAnimationPlayOffSceneP(void)
+{
+  // Test that an animation cannot be played, when the actor is off-stage.
+  // And the property value and the current property value should not be changed in the case.
+
+  TestApplication application;
+
+  Actor   actor = Actor::New();
+  Vector3 basePosition(Vector3::ZERO);
+  DALI_TEST_EQUALS(actor.GetCurrentProperty<Vector3>(Actor::Property::POSITION), basePosition, TEST_LOCATION);
+  // Not added to the stage yet!
+
+  // Build the animation
+  float     durationSeconds(1.0f);
+  Animation animation = Animation::New(durationSeconds);
+  Vector3   targetPosition(100.0f, 100.0f, 100.0f);
+  animation.AnimateTo(Property(actor, Actor::Property::POSITION), targetPosition, AlphaFunction::LINEAR);
+
+  // Start the animation
+  animation.Play();
+
+  bool                 signalReceived(false);
+  AnimationFinishCheck finishCheck(signalReceived);
+  animation.FinishedSignal().Connect(&application, finishCheck);
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds * 1000.0f) + 1u /*just beyond the animation duration*/);
+
+  application.SendNotification();
+  finishCheck.CheckSignalReceived();
+
+  // An animation can't be played. The position shouldn't be changed.
+  DALI_TEST_EQUALS(actor.GetCurrentProperty<Vector3>(Actor::Property::POSITION), basePosition, TEST_LOCATION);
+  DALI_TEST_EQUALS(actor.GetProperty<Vector3>(Actor::Property::POSITION), basePosition, TEST_LOCATION);
+
+  // Add to the stage
+  application.GetScene().Add(actor);
+
+  // Start the animation again
+  animation.Play();
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds * 1000.0f) + 1u /*just beyond the animation duration*/);
+
+  // We did expect the animation to finish
+  application.SendNotification();
+  finishCheck.CheckSignalReceived();
+
+  DALI_TEST_EQUALS(actor.GetCurrentProperty<Vector3>(Actor::Property::POSITION), targetPosition, TEST_LOCATION);
+  DALI_TEST_EQUALS(actor.GetProperty<Vector3>(Actor::Property::POSITION), targetPosition, TEST_LOCATION);
+
+  // Reset the position
+  actor[Actor::Property::POSITION] = basePosition;
+
+  application.SendNotification();
+  application.Render();
+
+  // Create an animator again
+  animation.Clear();
+  animation.AnimateTo(Property(actor, Actor::Property::POSITION), targetPosition, AlphaFunction::LINEAR);
+
+  // Remove from the stage
+  application.GetScene().Remove(actor);
+
+  signalReceived = false;
+
+  // Start the animation again
+  animation.Play();
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds * 1000.0f) + 1u /*just beyond the animation duration*/);
+
+  application.SendNotification();
+  finishCheck.CheckSignalReceived();
+
+  // An animation can't be played. The position shouldn't be changed.
+  DALI_TEST_EQUALS(actor.GetCurrentProperty<Vector3>(Actor::Property::POSITION), basePosition, TEST_LOCATION);
+  DALI_TEST_EQUALS(actor.GetProperty<Vector3>(Actor::Property::POSITION), basePosition, TEST_LOCATION);
+
+  END_TEST;
+}
+
 int UtcDaliAnimationPlayOffSceneDiscardP(void)
 {
-  // Test that an animation can be played, when the actor is off-stage.
+  // Test that an animation cannot be played, when the actor is off-stage.
   // When the actor is added to the stage, it should appear at the current position
   // i.e. where it would have been anyway, if on-stage from the beginning.
 
@@ -2249,7 +2332,9 @@ int UtcDaliAnimationPlayOffSceneDiscardP(void)
   // We didn't expect the animation to finish yet
   application.SendNotification();
   finishCheck.CheckSignalNotReceived();
-  DALI_TEST_EQUALS(actor.GetCurrentProperty<Vector3>(Actor::Property::POSITION), Vector3(20, 20, 20), TEST_LOCATION);
+
+  // An animation can't be played. The position shouldn't be changed.
+  DALI_TEST_EQUALS(actor.GetCurrentProperty<Vector3>(Actor::Property::POSITION), basePosition, TEST_LOCATION);
 
   // Add to the stage
   application.GetScene().Add(actor);
@@ -2310,7 +2395,7 @@ int UtcDaliAnimationPlayOffSceneDiscardP(void)
 
 int UtcDaliAnimationPlayOffSceneBakeFinalP(void)
 {
-  // Test that an animation can be played, when the actor is off-stage.
+  // Test that an animation cannot be played, when the actor is off-stage.
   // When the actor is added to the stage, it should appear at the current position
   // i.e. where it would have been anyway, if on-stage from the beginning.
 
@@ -2340,7 +2425,9 @@ int UtcDaliAnimationPlayOffSceneBakeFinalP(void)
   // We didn't expect the animation to finish yet
   application.SendNotification();
   finishCheck.CheckSignalNotReceived();
-  DALI_TEST_EQUALS(actor.GetCurrentProperty<Vector3>(Actor::Property::POSITION), Vector3(20, 20, 20), TEST_LOCATION);
+
+  // An animation can't be played. The position shouldn't be changed.
+  DALI_TEST_EQUALS(actor.GetCurrentProperty<Vector3>(Actor::Property::POSITION), basePosition, TEST_LOCATION);
 
   // Add to the stage
   application.GetScene().Add(actor);
@@ -2394,7 +2481,7 @@ int UtcDaliAnimationPlayOffSceneBakeFinalP(void)
 
 int UtcDaliAnimationPlayOffSceneBakeP(void)
 {
-  // Test that an animation can be played, when the actor is off-stage.
+  // Test that an animation cannot be played, when the actor is off-stage.
   // When the actor is added to the stage, it should appear at the current position
   // i.e. where it would have been anyway, if on-stage from the beginning.
 
@@ -2425,7 +2512,9 @@ int UtcDaliAnimationPlayOffSceneBakeP(void)
   // We didn't expect the animation to finish yet
   application.SendNotification();
   finishCheck.CheckSignalNotReceived();
-  DALI_TEST_EQUALS(actor.GetCurrentProperty<Vector3>(Actor::Property::POSITION), Vector3(20, 20, 20), TEST_LOCATION);
+
+  // An animation can't be played. The position shouldn't be changed.
+  DALI_TEST_EQUALS(actor.GetCurrentProperty<Vector3>(Actor::Property::POSITION), basePosition, TEST_LOCATION);
 
   // Add to the stage
   application.GetScene().Add(actor);
@@ -3082,6 +3171,174 @@ int UtcDaliAnimationStopSetPositionP(void)
   END_TEST;
 }
 
+int UtcDaliAnimationStopEmitFinishedSignalImmediateP(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  application.GetScene().Add(actor);
+
+  // Build the animation
+  float     durationSeconds(1.0f);
+  Animation animation = Animation::New(durationSeconds);
+  Vector3   targetPosition(100.0f, 100.0f, 100.0f);
+  animation.AnimateTo(Property(actor, Actor::Property::POSITION), targetPosition, AlphaFunction::LINEAR);
+
+  bool                 signalReceived(false);
+  AnimationFinishCheck finishCheck(signalReceived);
+  animation.FinishedSignal().Connect(&application, finishCheck);
+
+  // Play
+  {
+    tet_printf("Play and Stop immediately\n");
+    // Start the animation, and stop immediately.
+    animation.Play();
+    animation.Stop();
+
+    finishCheck.CheckSignalNotReceived();
+
+    application.SendNotification();
+    application.Render(0);
+
+    // expect finished signal recieved due to Stop API.
+    application.SendNotification();
+    finishCheck.CheckSignalReceived();
+    finishCheck.Reset();
+
+    application.SendNotification();
+    application.Render(0);
+  }
+  // Play multiple times
+  {
+    tet_printf("Play and Stop immediately 2\n");
+    // Start the animation, and stop immediately.
+    animation.Play();
+    animation.Stop();
+    animation.Play();
+    animation.Stop();
+    animation.Play();
+    animation.Play();
+    animation.Stop();
+
+    finishCheck.CheckSignalNotReceived();
+
+    application.SendNotification();
+    application.Render(0);
+
+    // expect finished signal recieved due to Stop API.
+    application.SendNotification();
+    finishCheck.CheckSignalReceived();
+    finishCheck.Reset();
+
+    application.SendNotification();
+    application.Render(0);
+  }
+  // PlayAfter
+  {
+    tet_printf("PlayAfter and Stop immediately\n");
+    // Start the animation, and stop immediately.
+    animation.PlayAfter(1.0f);
+    animation.Stop();
+
+    finishCheck.CheckSignalNotReceived();
+
+    application.SendNotification();
+    application.Render(0);
+
+    // expect finished signal recieved due to Stop API.
+    application.SendNotification();
+    finishCheck.CheckSignalReceived();
+    finishCheck.Reset();
+
+    application.SendNotification();
+    application.Render(0);
+  }
+  // PlayFrom
+  {
+    tet_printf("PlayFrom and Stop immediately\n");
+    // Start the animation, and stop immediately.
+    animation.PlayFrom(0.5f);
+    animation.Stop();
+
+    finishCheck.CheckSignalNotReceived();
+
+    application.SendNotification();
+    application.Render(0);
+
+    // expect finished signal recieved due to Stop API.
+    application.SendNotification();
+    finishCheck.CheckSignalReceived();
+    finishCheck.Reset();
+
+    application.SendNotification();
+    application.Render(0);
+  }
+  // Play and Pause
+  {
+    tet_printf("Play and Pause and Stop immediately\n");
+    // Pause the animation, and stop immediately.
+    animation.Play();
+    animation.Pause();
+    animation.Stop();
+
+    finishCheck.CheckSignalNotReceived();
+
+    application.SendNotification();
+    application.Render(0);
+
+    // expect finished signal recieved due to Stop API.
+    application.SendNotification();
+    finishCheck.CheckSignalReceived();
+    finishCheck.Reset();
+
+    application.SendNotification();
+    application.Render(0);
+  }
+
+  // Check finished signal not emmited if animation was not play state.
+  {
+    tet_printf("Check whether stop-only case didnt send finished signal\n");
+    // Stop only.
+    animation.Stop();
+    animation.Stop();
+    animation.Stop();
+
+    finishCheck.CheckSignalNotReceived();
+
+    application.SendNotification();
+    application.Render(0);
+
+    // expect finished signal not recieved.
+    application.SendNotification();
+    finishCheck.CheckSignalNotReceived();
+    finishCheck.Reset();
+
+    application.SendNotification();
+    application.Render(0);
+  }
+  {
+    tet_printf("Check whether pause-stop case didnt send finished signal\n");
+    // Pause and Stop.
+    animation.Pause();
+    animation.Stop();
+
+    finishCheck.CheckSignalNotReceived();
+
+    application.SendNotification();
+    application.Render(0);
+
+    // expect finished signal not recieved.
+    application.SendNotification();
+    finishCheck.CheckSignalNotReceived();
+    finishCheck.Reset();
+
+    application.SendNotification();
+    application.Render(0);
+  }
+
+  END_TEST;
+}
+
 int UtcDaliAnimationClearP(void)
 {
   TestApplication application;
@@ -3149,55 +3406,290 @@ int UtcDaliAnimationClearP(void)
   END_TEST;
 }
 
-int UtcDaliAnimationFinishedSignalP(void)
+int UtcDaliAnimationClearIgnoreFinishedSignal(void)
 {
   TestApplication application;
 
-  // Start the empty animation
+  Actor actor = Actor::New();
+  application.GetScene().Add(actor);
+
+  // Build the animation
   float     durationSeconds(1.0f);
   Animation animation = Animation::New(durationSeconds);
+  Vector3   targetPosition(100.0f, 100.0f, 100.0f);
+  animation.AnimateTo(Property(actor, Actor::Property::POSITION), targetPosition, AlphaFunction::LINEAR);
+
+  Vector3 fiftyPercentProgress(targetPosition * 0.5f);
+
+  // Start the animation
   animation.Play();
 
   bool                 signalReceived(false);
   AnimationFinishCheck finishCheck(signalReceived);
   animation.FinishedSignal().Connect(&application, finishCheck);
 
-  application.SendNotification();
-  application.Render(static_cast<unsigned int>(durationSeconds * 1000.0f) + 1u /*beyond the animation duration*/);
+  // Check finished signal not emmited if animation was cleared.
+  {
+    tet_printf("Check whether stop and clear case didnt send finished signal\n");
+    // Play the animation, and stop after animation finished naturally, and clear.
+    animation.Play();
 
-  // We did expect the animation to finish
-  application.SendNotification();
-  finishCheck.CheckSignalReceived();
-  END_TEST;
-}
+    application.SendNotification();
 
-int UtcDaliAnimationAnimateByBooleanP(void)
-{
-  TestApplication application;
+    animation.Stop();
+    animation.Clear();
 
-  Actor actor = Actor::New();
+    application.SendNotification();
+    finishCheck.CheckSignalNotReceived();
+    finishCheck.Reset();
 
-  // Register a boolean property
-  bool            startValue(false);
-  Property::Index index = actor.RegisterProperty("testProperty", startValue);
-  application.GetScene().Add(actor);
-  DALI_TEST_CHECK(actor.GetProperty<bool>(index) == startValue);
-  DALI_TEST_CHECK(actor.GetCurrentProperty<bool>(index) == startValue);
+    // Finish animation naturally. (Note that dali don't call finished callback even if one render frame spend more than duration.)
+    application.Render(static_cast<uint32_t>(durationSeconds * 500.0f));
+    application.Render(static_cast<uint32_t>(durationSeconds * 500.0f) + 10u);
+    application.SendNotification();
 
-  // Build the animation
-  float      durationSeconds(2.0f);
-  Animation  animation = Animation::New(durationSeconds);
-  const bool relativeValue(true);
-  const bool finalValue(false || relativeValue);
-  animation.AnimateBy(Property(actor, index), relativeValue);
+    // expect finished signal not recieved.
+    finishCheck.CheckSignalNotReceived();
+    finishCheck.Reset();
 
-  // Start the animation
-  animation.Play();
+    application.SendNotification();
+    application.Render(0);
+  }
+  {
+    tet_printf("Check whether stop and clear and render-well case send finished signal\n");
+    // Play the animation, and stop after animation finished naturally, and clear, and play again.
+    animation.PlayAfter(durationSeconds);
 
-  // Target value should be retrievable straight away
-  DALI_TEST_EQUALS(actor.GetProperty<bool>(index), finalValue, TEST_LOCATION);
+    application.SendNotification();
 
-  bool                 signalReceived(false);
+    // delay 50%.
+    application.Render(static_cast<uint32_t>(durationSeconds * 500.0f));
+
+    animation.Stop();
+    animation.Clear();
+    animation.Play();
+
+    application.SendNotification();
+    finishCheck.CheckSignalNotReceived();
+    finishCheck.Reset();
+
+    // Finish animation naturally. (Note that dali don't call finished callback even if one render frame spend more than duration.)
+    application.Render(static_cast<uint32_t>(durationSeconds * 500.0f));
+    application.Render(static_cast<uint32_t>(durationSeconds * 500.0f) + 10u);
+    application.SendNotification();
+
+    // expect finished signal recieved due to Animation finished.
+    application.SendNotification();
+    finishCheck.CheckSignalReceived();
+    finishCheck.Reset();
+
+    application.SendNotification();
+    application.Render(0);
+  }
+
+  END_TEST;
+}
+
+int UtcDaliAnimationEmptyAnimatorAndLoopCount(void)
+{
+  // Clear and play the empty animation, and get the state values.
+  TestApplication application;
+
+  float     durationSeconds(1.0f);
+  Animation animation = Animation::New(durationSeconds);
+  animation.SetLoopCount(3);
+
+  bool                 signalReceived(false);
+  AnimationFinishCheck finishCheck(signalReceived);
+  animation.FinishedSignal().Connect(&application, finishCheck);
+
+  try
+  {
+    DALI_TEST_EQUALS(animation.GetState(), Dali::Animation::STOPPED, TEST_LOCATION);
+    DALI_TEST_EQUALS(animation.GetCurrentLoop(), 0, TEST_LOCATION);
+    application.SendNotification();
+    application.Render();
+
+    animation.Play();
+
+    DALI_TEST_EQUALS(animation.GetState(), Dali::Animation::PLAYING, TEST_LOCATION);
+    DALI_TEST_EQUALS(animation.GetCurrentLoop(), 0, TEST_LOCATION);
+    application.SendNotification();
+    application.Render(1500 /* 150% of loop. */);
+
+    DALI_TEST_EQUALS(animation.GetState(), Dali::Animation::PLAYING, TEST_LOCATION);
+    DALI_TEST_EQUALS(animation.GetCurrentLoop(), 1, TEST_LOCATION);
+
+    application.SendNotification();
+    application.Render(1400 /* 290% of loop. */);
+
+    DALI_TEST_EQUALS(animation.GetState(), Dali::Animation::PLAYING, TEST_LOCATION);
+    DALI_TEST_EQUALS(animation.GetCurrentLoop(), 2, TEST_LOCATION);
+
+    application.SendNotification();
+    application.Render(100 + 1100 /* 300% of loop. and extra 110%. */);
+    application.SendNotification(); // Notification trigger.
+
+    DALI_TEST_EQUALS(animation.GetState(), Dali::Animation::STOPPED, TEST_LOCATION);
+    DALI_TEST_EQUALS(animation.GetCurrentLoop(), 3, TEST_LOCATION);
+
+    tet_printf("Check wether empty animation also call finished signal.\n");
+    finishCheck.CheckSignalReceived();
+    finishCheck.Reset();
+
+    animation.Play();
+
+    DALI_TEST_EQUALS(animation.GetState(), Dali::Animation::PLAYING, TEST_LOCATION);
+    application.SendNotification();
+    application.Render(0 /* 0% of loop. */);
+
+    // LoopCount beome 0 again.
+    DALI_TEST_EQUALS(animation.GetCurrentLoop(), 0, TEST_LOCATION);
+
+    application.Render(1500 /* 150% of loop. */);
+
+    DALI_TEST_EQUALS(animation.GetState(), Dali::Animation::PLAYING, TEST_LOCATION);
+    DALI_TEST_EQUALS(animation.GetCurrentLoop(), 1, TEST_LOCATION);
+
+    animation.Pause();
+
+    application.SendNotification();
+    application.Render(2500 /* 150% of loop. (Since it is paused) */);
+
+    DALI_TEST_EQUALS(animation.GetState(), Dali::Animation::PAUSED, TEST_LOCATION);
+    DALI_TEST_EQUALS(animation.GetCurrentLoop(), 1, TEST_LOCATION);
+
+    animation.Play();
+
+    application.SendNotification();
+    application.Render(1000 /* 250% of loop. */);
+
+    DALI_TEST_EQUALS(animation.GetState(), Dali::Animation::PLAYING, TEST_LOCATION);
+    DALI_TEST_EQUALS(animation.GetCurrentLoop(), 2, TEST_LOCATION);
+
+    animation.Clear();
+
+    DALI_TEST_EQUALS(animation.GetState(), Dali::Animation::STOPPED, TEST_LOCATION);
+
+    application.SendNotification();
+    application.Render(500 + 100 /* 300% of loop + 10% over the loop. */);
+    application.SendNotification(); // Notification trigger.
+
+    DALI_TEST_EQUALS(animation.GetCurrentLoop(), 0, TEST_LOCATION);
+
+    tet_printf("Check animation completed signal not recieved even if animation finished normally at this loop.\n");
+    finishCheck.CheckSignalNotReceived();
+
+    application.SendNotification();
+    application.Render(1100);
+    application.Render(1100);
+    application.Render(1100 /* Over the loop count */);
+    application.SendNotification(); // Notification trigger.
+
+    tet_printf("Check animation completed signal not recieved even if animation finished normally.\n");
+    finishCheck.CheckSignalNotReceived();
+
+    animation.Play();
+
+    application.SendNotification();
+    application.Render(1500 /* 150% of loop. */);
+
+    DALI_TEST_EQUALS(animation.GetState(), Dali::Animation::PLAYING, TEST_LOCATION);
+    DALI_TEST_EQUALS(animation.GetCurrentLoop(), 1, TEST_LOCATION);
+
+    animation.Stop();
+    animation.Clear();
+
+    DALI_TEST_EQUALS(animation.GetState(), Dali::Animation::STOPPED, TEST_LOCATION);
+
+    application.SendNotification();
+    application.Render();
+    application.SendNotification(); // Notification trigger.
+
+    DALI_TEST_EQUALS(animation.GetCurrentLoop(), 0, TEST_LOCATION);
+
+    tet_printf("Check animation completed signal not recieved even if we call Stop forcibly.\n");
+    finishCheck.CheckSignalNotReceived();
+
+    animation.Clear();
+
+    DALI_TEST_EQUALS(animation.GetState(), Dali::Animation::STOPPED, TEST_LOCATION);
+
+    animation.Play();
+
+    DALI_TEST_EQUALS(animation.GetState(), Dali::Animation::PLAYING, TEST_LOCATION);
+    DALI_TEST_EQUALS(animation.GetCurrentLoop(), 0, TEST_LOCATION);
+
+    application.SendNotification();
+    application.Render(1100);
+    application.Render(1100);
+    application.Render(1100 /* Over the loop count */);
+    application.SendNotification(); // Notification trigger.
+
+    DALI_TEST_EQUALS(animation.GetState(), Dali::Animation::STOPPED, TEST_LOCATION);
+    DALI_TEST_EQUALS(animation.GetCurrentLoop(), 3, TEST_LOCATION);
+
+    tet_printf("Check animation completed signal recieved. (Since clear didn't disconnect complete signal)\n");
+    finishCheck.CheckSignalReceived();
+    finishCheck.Reset();
+  }
+  catch(...)
+  {
+    DALI_TEST_CHECK(false); // Should not get here
+  }
+
+  END_TEST;
+}
+
+int UtcDaliAnimationFinishedSignalP(void)
+{
+  TestApplication application;
+
+  // Start the empty animation
+  float     durationSeconds(1.0f);
+  Animation animation = Animation::New(durationSeconds);
+  animation.Play();
+
+  bool                 signalReceived(false);
+  AnimationFinishCheck finishCheck(signalReceived);
+  animation.FinishedSignal().Connect(&application, finishCheck);
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds * 1000.0f) + 1u /*beyond the animation duration*/);
+
+  // We did expect the animation to finish
+  application.SendNotification();
+  finishCheck.CheckSignalReceived();
+  END_TEST;
+}
+
+int UtcDaliAnimationAnimateByBooleanP(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+
+  // Register a boolean property
+  bool            startValue(false);
+  Property::Index index = actor.RegisterProperty("testProperty", startValue);
+  application.GetScene().Add(actor);
+  DALI_TEST_CHECK(actor.GetProperty<bool>(index) == startValue);
+  DALI_TEST_CHECK(actor.GetCurrentProperty<bool>(index) == startValue);
+
+  // Build the animation
+  float      durationSeconds(2.0f);
+  Animation  animation = Animation::New(durationSeconds);
+  const bool relativeValue(true);
+  const bool finalValue(false || relativeValue);
+  animation.AnimateBy(Property(actor, index), relativeValue);
+
+  // Start the animation
+  animation.Play();
+
+  // Target value should be retrievable straight away
+  DALI_TEST_EQUALS(actor.GetProperty<bool>(index), finalValue, TEST_LOCATION);
+
+  bool                 signalReceived(false);
   AnimationFinishCheck finishCheck(signalReceived);
   animation.FinishedSignal().Connect(&application, finishCheck);
 
@@ -9099,6 +9591,244 @@ int UtcDaliAnimationKeyFrames07N(void)
   END_TEST;
 }
 
+int UtcDaliAnimationKeyFramesGetKeyFrameCountP(void)
+{
+  TestApplication application;
+
+  KeyFrames keyFrames = KeyFrames::New();
+
+  DALI_TEST_EQUALS(DevelKeyFrames::GetKeyFrameCount(keyFrames), 0, TEST_LOCATION);
+
+  keyFrames.Add(0.0f, Vector4(0.0f, 0.0f, 0.0f, 0.6f));
+  keyFrames.Add(0.6f, Vector4(0.0f, 0.0f, 0.0f, 0.3f));
+  keyFrames.Add(1.0f, Vector4(0.0f, 0.0f, 0.0f, 0.8f));
+
+  DALI_TEST_EQUALS(DevelKeyFrames::GetKeyFrameCount(keyFrames), 3, TEST_LOCATION);
+
+  END_TEST;
+}
+
+int UtcDaliAnimationKeyFramesGetKeyFrameP(void)
+{
+  TestApplication application;
+
+  float   inputTime  = 0.6f;
+  Vector4 inputValue = Vector4(0.0f, 0.0f, 0.0f, 0.3f);
+
+  float           outputTime;
+  Property::Value outputValue;
+  KeyFrames       keyFrames = KeyFrames::New();
+
+  DevelKeyFrames::GetKeyFrame(keyFrames, 0, outputTime, outputValue);
+
+  DALI_TEST_EQUALS(outputValue.GetType(), Property::Type::NONE, TEST_LOCATION);
+
+  keyFrames.Add(0.0f, Vector4(0.0f, 0.0f, 0.0f, 0.6f));
+  keyFrames.Add(inputTime, inputValue);
+  keyFrames.Add(1.0f, Vector4(0.0f, 0.0f, 0.0f, 0.8f));
+
+  DevelKeyFrames::GetKeyFrame(keyFrames, 3, outputTime, outputValue);
+
+  DALI_TEST_EQUALS(outputValue.GetType(), Property::Type::NONE, TEST_LOCATION);
+
+  DevelKeyFrames::GetKeyFrame(keyFrames, 1, outputTime, outputValue);
+
+  DALI_TEST_EQUALS(outputTime, inputTime, TEST_LOCATION);
+  DALI_TEST_EQUALS(outputValue.GetType(), Property::Type::VECTOR4, TEST_LOCATION);
+  DALI_TEST_EQUALS(outputValue.Get<Vector4>(), inputValue, TEST_LOCATION);
+
+  END_TEST;
+}
+
+int UtcDaliAnimationKeyFramesSetKeyFrameP(void)
+{
+  TestApplication application;
+
+  float   inputTime  = 0.6f;
+  Vector4 inputValue = Vector4(0.0f, 0.0f, 0.0f, 0.3f);
+
+  KeyFrames keyFrames = KeyFrames::New();
+  keyFrames.Add(0.0f, Vector4(0.0f, 0.0f, 0.0f, 0.6f));
+  keyFrames.Add(inputTime, inputValue);
+  keyFrames.Add(1.0f, Vector4(0.0f, 0.0f, 0.0f, 0.8f));
+
+  float           outputTime;
+  Property::Value outputValue;
+
+  DevelKeyFrames::GetKeyFrame(keyFrames, 3, outputTime, outputValue);
+
+  DALI_TEST_EQUALS(outputValue.GetType(), Property::Type::NONE, TEST_LOCATION);
+
+  DevelKeyFrames::GetKeyFrame(keyFrames, 1, outputTime, outputValue);
+
+  DALI_TEST_EQUALS(outputTime, inputTime, TEST_LOCATION);
+  DALI_TEST_EQUALS(outputValue.GetType(), Property::Type::VECTOR4, TEST_LOCATION);
+  DALI_TEST_EQUALS(outputValue.Get<Vector4>(), inputValue, TEST_LOCATION);
+
+  Vector4 newValue = Vector4(1.0f, 0.2f, 0.6f, 0.9f);
+
+  DevelKeyFrames::SetKeyFrameValue(keyFrames, 1, newValue);
+
+  DevelKeyFrames::GetKeyFrame(keyFrames, 1, outputTime, outputValue);
+
+  DALI_TEST_EQUALS(outputTime, inputTime, TEST_LOCATION);
+  DALI_TEST_EQUALS(outputValue.GetType(), Property::Type::VECTOR4, TEST_LOCATION);
+  DALI_TEST_EQUALS(outputValue.Get<Vector4>(), newValue, TEST_LOCATION);
+
+  Vector3 newUnmatchedValue = Vector3(0.0f, 1.0f, 0.2f);
+
+  // Check nothing happened if we set unmatched value type.
+  DevelKeyFrames::SetKeyFrameValue(keyFrames, 1, newUnmatchedValue);
+
+  DevelKeyFrames::GetKeyFrame(keyFrames, 1, outputTime, outputValue);
+
+  DALI_TEST_EQUALS(outputTime, inputTime, TEST_LOCATION);
+  DALI_TEST_EQUALS(outputValue.GetType(), Property::Type::VECTOR4, TEST_LOCATION);
+  DALI_TEST_EQUALS(outputValue.Get<Vector4>(), newValue, TEST_LOCATION);
+
+  END_TEST;
+}
+
+int UtcDaliAnimationKeyFramesOptimizeKeyFramesLinearP(void)
+{
+  TestApplication application;
+
+  KeyFrames keyFrames = KeyFrames::New();
+
+  float firstExpectTime   = 0.0f;
+  float firstExpectValue  = 0.0f;
+  float secondExpectTime  = 0.4f;
+  float secondExpectValue = 1.2f;
+  float thirdExpectTime   = 0.8f;
+  float thirdExpectValue  = 0.4f;
+  float fourthExpectTime  = 1.0f;
+  float fourthExpectValue = 0.7f;
+
+  float interpolateLate = 0.5f;
+
+  tet_printf("first - second phase test\n");
+
+  DALI_TEST_EQUALS(false, DevelKeyFrames::OptimizeKeyFramesLinear(keyFrames), TEST_LOCATION);
+  DALI_TEST_EQUALS(DevelKeyFrames::GetKeyFrameCount(keyFrames), 0, TEST_LOCATION);
+
+  keyFrames.Add(firstExpectTime, firstExpectValue);
+  DALI_TEST_EQUALS(false, DevelKeyFrames::OptimizeKeyFramesLinear(keyFrames), TEST_LOCATION);
+  DALI_TEST_EQUALS(DevelKeyFrames::GetKeyFrameCount(keyFrames), 1, TEST_LOCATION);
+
+  keyFrames.Add(firstExpectTime * (1.0f - interpolateLate) + secondExpectTime * interpolateLate, firstExpectValue * (1.0f - interpolateLate) + secondExpectValue * interpolateLate);
+  DALI_TEST_EQUALS(false, DevelKeyFrames::OptimizeKeyFramesLinear(keyFrames), TEST_LOCATION);
+  DALI_TEST_EQUALS(DevelKeyFrames::GetKeyFrameCount(keyFrames), 2, TEST_LOCATION);
+
+  keyFrames.Add(secondExpectTime, secondExpectValue);
+
+  DALI_TEST_EQUALS(DevelKeyFrames::GetKeyFrameCount(keyFrames), 3, TEST_LOCATION);
+  DALI_TEST_EQUALS(true, DevelKeyFrames::OptimizeKeyFramesLinear(keyFrames), TEST_LOCATION);
+  DALI_TEST_EQUALS(DevelKeyFrames::GetKeyFrameCount(keyFrames), 2, TEST_LOCATION);
+
+  float           outputTime;
+  Property::Value outputValue;
+
+  DevelKeyFrames::GetKeyFrame(keyFrames, 0, outputTime, outputValue);
+
+  DALI_TEST_EQUALS(outputTime, firstExpectTime, TEST_LOCATION);
+  DALI_TEST_EQUALS(outputValue.GetType(), Property::Type::FLOAT, TEST_LOCATION);
+  DALI_TEST_EQUALS(outputValue.Get<float>(), firstExpectValue, TEST_LOCATION);
+
+  DevelKeyFrames::GetKeyFrame(keyFrames, 1, outputTime, outputValue);
+
+  DALI_TEST_EQUALS(outputTime, secondExpectTime, TEST_LOCATION);
+  DALI_TEST_EQUALS(outputValue.GetType(), Property::Type::FLOAT, TEST_LOCATION);
+  DALI_TEST_EQUALS(outputValue.Get<float>(), secondExpectValue, TEST_LOCATION);
+
+  tet_printf("second - third phase test\n");
+
+  interpolateLate = 0.3f;
+  keyFrames.Add(secondExpectTime * (1.0f - interpolateLate) + thirdExpectTime * interpolateLate, secondExpectValue * (1.0f - interpolateLate) + thirdExpectValue * interpolateLate);
+  DALI_TEST_EQUALS(DevelKeyFrames::GetKeyFrameCount(keyFrames), 3, TEST_LOCATION);
+
+  interpolateLate = 0.4f;
+  keyFrames.Add(secondExpectTime * (1.0f - interpolateLate) + thirdExpectTime * interpolateLate, secondExpectValue * (1.0f - interpolateLate) + thirdExpectValue * interpolateLate);
+  DALI_TEST_EQUALS(DevelKeyFrames::GetKeyFrameCount(keyFrames), 4, TEST_LOCATION);
+
+  interpolateLate = 0.5f;
+  keyFrames.Add(secondExpectTime * (1.0f - interpolateLate) + thirdExpectTime * interpolateLate, secondExpectValue * (1.0f - interpolateLate) + thirdExpectValue * interpolateLate);
+  DALI_TEST_EQUALS(DevelKeyFrames::GetKeyFrameCount(keyFrames), 5, TEST_LOCATION);
+
+  interpolateLate = 0.8f;
+  keyFrames.Add(secondExpectTime * (1.0f - interpolateLate) + thirdExpectTime * interpolateLate, secondExpectValue * (1.0f - interpolateLate) + thirdExpectValue * interpolateLate);
+  DALI_TEST_EQUALS(DevelKeyFrames::GetKeyFrameCount(keyFrames), 6, TEST_LOCATION);
+
+  keyFrames.Add(thirdExpectTime, thirdExpectValue);
+  DALI_TEST_EQUALS(DevelKeyFrames::GetKeyFrameCount(keyFrames), 7, TEST_LOCATION);
+
+  DALI_TEST_EQUALS(true, DevelKeyFrames::OptimizeKeyFramesLinear(keyFrames), TEST_LOCATION);
+  DALI_TEST_EQUALS(DevelKeyFrames::GetKeyFrameCount(keyFrames), 3, TEST_LOCATION);
+
+  DevelKeyFrames::GetKeyFrame(keyFrames, 0, outputTime, outputValue);
+
+  DALI_TEST_EQUALS(outputTime, firstExpectTime, TEST_LOCATION);
+  DALI_TEST_EQUALS(outputValue.GetType(), Property::Type::FLOAT, TEST_LOCATION);
+  DALI_TEST_EQUALS(outputValue.Get<float>(), firstExpectValue, TEST_LOCATION);
+
+  DevelKeyFrames::GetKeyFrame(keyFrames, 1, outputTime, outputValue);
+
+  DALI_TEST_EQUALS(outputTime, secondExpectTime, TEST_LOCATION);
+  DALI_TEST_EQUALS(outputValue.GetType(), Property::Type::FLOAT, TEST_LOCATION);
+  DALI_TEST_EQUALS(outputValue.Get<float>(), secondExpectValue, TEST_LOCATION);
+
+  DevelKeyFrames::GetKeyFrame(keyFrames, 2, outputTime, outputValue);
+
+  DALI_TEST_EQUALS(outputTime, thirdExpectTime, TEST_LOCATION);
+  DALI_TEST_EQUALS(outputValue.GetType(), Property::Type::FLOAT, TEST_LOCATION);
+  DALI_TEST_EQUALS(outputValue.Get<float>(), thirdExpectValue, TEST_LOCATION);
+
+  tet_printf("third - fourth phase test. Test what we skip same progress.\n");
+
+  interpolateLate = 0.3f;
+  keyFrames.Add(thirdExpectTime * (1.0f - interpolateLate) + fourthExpectTime * interpolateLate, thirdExpectValue * (1.0f - interpolateLate) + fourthExpectValue * interpolateLate);
+  DALI_TEST_EQUALS(DevelKeyFrames::GetKeyFrameCount(keyFrames), 4, TEST_LOCATION);
+
+  interpolateLate = 0.5f;
+  keyFrames.Add(thirdExpectTime * (1.0f - interpolateLate) + fourthExpectTime * interpolateLate, thirdExpectValue * (1.0f - interpolateLate) + fourthExpectValue * interpolateLate);
+  DALI_TEST_EQUALS(DevelKeyFrames::GetKeyFrameCount(keyFrames), 5, TEST_LOCATION);
+
+  interpolateLate = 0.8f;
+  keyFrames.Add(thirdExpectTime * (1.0f - interpolateLate) + fourthExpectTime * interpolateLate, thirdExpectValue * (1.0f - interpolateLate) + fourthExpectValue * interpolateLate);
+  DALI_TEST_EQUALS(DevelKeyFrames::GetKeyFrameCount(keyFrames), 6, TEST_LOCATION);
+
+  keyFrames.Add(fourthExpectTime, fourthExpectValue);
+  DALI_TEST_EQUALS(DevelKeyFrames::GetKeyFrameCount(keyFrames), 7, TEST_LOCATION);
+
+  DALI_TEST_EQUALS(true, DevelKeyFrames::OptimizeKeyFramesLinear(keyFrames), TEST_LOCATION);
+  DALI_TEST_EQUALS(DevelKeyFrames::GetKeyFrameCount(keyFrames), 4, TEST_LOCATION);
+
+  DevelKeyFrames::GetKeyFrame(keyFrames, 0, outputTime, outputValue);
+
+  DALI_TEST_EQUALS(outputTime, firstExpectTime, TEST_LOCATION);
+  DALI_TEST_EQUALS(outputValue.GetType(), Property::Type::FLOAT, TEST_LOCATION);
+  DALI_TEST_EQUALS(outputValue.Get<float>(), firstExpectValue, TEST_LOCATION);
+
+  DevelKeyFrames::GetKeyFrame(keyFrames, 1, outputTime, outputValue);
+
+  DALI_TEST_EQUALS(outputTime, secondExpectTime, TEST_LOCATION);
+  DALI_TEST_EQUALS(outputValue.GetType(), Property::Type::FLOAT, TEST_LOCATION);
+  DALI_TEST_EQUALS(outputValue.Get<float>(), secondExpectValue, TEST_LOCATION);
+
+  DevelKeyFrames::GetKeyFrame(keyFrames, 2, outputTime, outputValue);
+
+  DALI_TEST_EQUALS(outputTime, thirdExpectTime, TEST_LOCATION);
+  DALI_TEST_EQUALS(outputValue.GetType(), Property::Type::FLOAT, TEST_LOCATION);
+  DALI_TEST_EQUALS(outputValue.Get<float>(), thirdExpectValue, TEST_LOCATION);
+
+  DevelKeyFrames::GetKeyFrame(keyFrames, 3, outputTime, outputValue);
+
+  DALI_TEST_EQUALS(outputTime, fourthExpectTime, TEST_LOCATION);
+  DALI_TEST_EQUALS(outputValue.GetType(), Property::Type::FLOAT, TEST_LOCATION);
+  DALI_TEST_EQUALS(outputValue.Get<float>(), fourthExpectValue, TEST_LOCATION);
+
+  END_TEST;
+}
+
 int UtcDaliAnimationAnimateBetweenActorColorAlphaP(void)
 {
   TestApplication application;
@@ -12470,6 +13200,7 @@ int UtcDaliAnimationProgressSignalConnectionWithoutProgressMarkerP(void)
   application.SendNotification();
 
   tet_infoline("Ensure after animation has started playing that ProgressReachedSignal not emitted");
+  finishCheck.CheckSignalNotReceived();
   progressCheck.CheckSignalNotReceived();
 
   application.Render(static_cast<unsigned int>(durationSeconds * 900.0f) + 1u /*just beyond the animation duration*/);
@@ -12862,7 +13593,9 @@ int UtcDaliAnimationProgressCallbackWithLoopingP(void)
   for(int count = 0; count < loopCount; count++)
   {
     application.SendNotification();
-    application.Render(0);                                // start animation
+    application.Render(0); // start animation
+    finishCheck.CheckSignalNotReceived();
+
     application.Render(durationSeconds * 0.25 * 1000.0f); // 25% progress
     DALI_TEST_EQUALS(0.25f, animation.GetCurrentProgress(), TEST_LOCATION);
 
@@ -13089,14 +13822,19 @@ int UtcDaliAnimationProgressCallbackNegativeSpeed(void)
   animation.SetLooping(false);
   animation.SetLoopCount(4);
   animation.Play();
-  application.Render(0u);
-  application.SendNotification();
+  application.SendNotification(); // Send Stop event into update thread
+  application.Render(0u);         // Send Notification into event thread
+  application.SendNotification(); // Execute finished signal.
+
+  finishCheck.CheckSignalReceived(); // Due to stop called.
+  finishCheck.Reset();
 
   for(int count = 0; count < 4; count++)
   {
     application.SendNotification();
     application.Render(0); // start animation
     progressCheck.CheckSignalNotReceived();
+    finishCheck.CheckSignalNotReceived();
 
     application.SendNotification();
     application.Render(durationSeconds * 0.25 * 1000.0f); // 25% progress
@@ -13555,6 +14293,33 @@ void CheckPropertyValuesWhenCallingAnimationMethod(TestFunction functionToTest,
 
     DALI_TEST_EQUALS(actor.GetProperty(Actor::Property::POSITION).Get<Vector3>(), expectedValueTable[i].expectedGetPropertyValue, VECTOR3_EPSILON, TEST_LOCATION);
     DALI_TEST_EQUALS(actor.GetCurrentProperty(Actor::Property::POSITION).Get<Vector3>(), expectedValueTable[i].expectedGetPropertyValue, VECTOR3_EPSILON, TEST_LOCATION);
+
+    // If we call Clear before, The animation didn't give any effort to actor now. Let we check it
+    if(functionToTest == TestFunction::CLEAR)
+    {
+      actor.SetProperty(Actor::Property::POSITION, originalPosition);
+
+      DALI_TEST_EQUALS(actor.GetProperty(Actor::Property::POSITION).Get<Vector3>(), originalPosition, VECTOR3_EPSILON, TEST_LOCATION);
+      DALI_TEST_EQUALS(actor.GetCurrentProperty(Actor::Property::POSITION).Get<Vector3>(), expectedValueTable[i].expectedGetPropertyValue, VECTOR3_EPSILON, TEST_LOCATION);
+
+      application.SendNotification();
+      application.Render();
+
+      DALI_TEST_EQUALS(actor.GetProperty(Actor::Property::POSITION).Get<Vector3>(), originalPosition, VECTOR3_EPSILON, TEST_LOCATION);
+      DALI_TEST_EQUALS(actor.GetCurrentProperty(Actor::Property::POSITION).Get<Vector3>(), originalPosition, VECTOR3_EPSILON, TEST_LOCATION);
+
+      // Start the animation, which we already clear.
+      animation.Play();
+
+      DALI_TEST_EQUALS(actor.GetProperty(Actor::Property::POSITION).Get<Vector3>(), originalPosition, VECTOR3_EPSILON, TEST_LOCATION);
+      DALI_TEST_EQUALS(actor.GetCurrentProperty(Actor::Property::POSITION).Get<Vector3>(), originalPosition, VECTOR3_EPSILON, TEST_LOCATION);
+
+      application.SendNotification();
+      application.Render(halfAnimationDuration);
+
+      DALI_TEST_EQUALS(actor.GetProperty(Actor::Property::POSITION).Get<Vector3>(), originalPosition, VECTOR3_EPSILON, TEST_LOCATION);
+      DALI_TEST_EQUALS(actor.GetCurrentProperty(Actor::Property::POSITION).Get<Vector3>(), originalPosition, VECTOR3_EPSILON, TEST_LOCATION);
+    }
   }
 }
 } // unnamed namespace
@@ -13565,17 +14330,64 @@ int UtcDaliAnimationStopPropertyValue(void)
   END_TEST;
 }
 
-int UtcDaliAnimationClearPropertyValue(void)
+int UtcDaliAnimationClearPropertyValue01(void)
 {
   CheckPropertyValuesWhenCallingAnimationMethod(TestFunction::CLEAR, "UtcDaliAnimationStopPropertyValue");
   END_TEST;
 }
 
+int UtcDaliAnimationClearPropertyValue02(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  application.GetScene().Add(actor);
+
+  const float   durationSeconds(1.0f);
+  const Vector3 targetPosition1(10.0f, 10.0f, 10.0f);
+  const Vector3 targetPosition2(20.0f, 20.0f, 20.0f);
+
+  // Build the animation
+  Animation animation1 = Animation::New(durationSeconds);
+  animation1.AnimateTo(Property(actor, Actor::Property::POSITION), targetPosition1, AlphaFunction::LINEAR);
+  animation1.Play();
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds * 1000.0f) - 1u /*just less than the animation duration*/);
+
+  // The event side property should be set the current value immediately
+  DALI_TEST_EQUALS(actor.GetProperty(Actor::Property::POSITION).Get<Vector3>(), targetPosition1, VECTOR3_EPSILON, TEST_LOCATION);
+
+  application.SendNotification();
+  application.Render(2u /*just beyond the animation duration*/);
+
+  // Build a new animation
+  Animation animation2 = Animation::New(durationSeconds);
+  animation2.AnimateTo(Property(actor, Actor::Property::POSITION), targetPosition2, AlphaFunction::LINEAR);
+  animation2.Play();
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds * 1000.0f) - 1u /*just less than the animation duration*/);
+
+  // The event side property should be set the current value immediately
+  DALI_TEST_EQUALS(actor.GetProperty(Actor::Property::POSITION).Get<Vector3>(), targetPosition2, VECTOR3_EPSILON, TEST_LOCATION);
+
+  // Clear the first animation after finished
+  animation1.Clear();
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds * 1000.0f) - 1u /*just less than the animation duration*/);
+
+  // The property should not be changed.
+  DALI_TEST_EQUALS(actor.GetProperty(Actor::Property::POSITION).Get<Vector3>(), targetPosition2, VECTOR3_EPSILON, TEST_LOCATION);
+
+  END_TEST;
+}
+
 int UtcDaliAnimationPausePropertyValue(void)
 {
   const float   durationSeconds(1.0f);
   unsigned int  halfAnimationDuration(static_cast<unsigned int>(durationSeconds * 1000.0f * 0.5f));
-  const Vector3 originalPosition(Vector3::ZERO);
   const Vector3 targetPosition(10.0f, 10.0f, 10.0f);
   const Vector3 halfWayToTarget(targetPosition * 0.5f);
 
@@ -14705,3 +15517,433 @@ int UtcDaliKeyFramesGetTypeNegative(void)
   }
   END_TEST;
 }
+
+int UtcDaliAnimationSetGetBlendPoint(void)
+{
+  TestApplication application;
+
+  Animation animation = Animation::New(1.0f);
+  DALI_TEST_EQUALS(animation.GetBlendPoint(), 0.0f, 0.01f, TEST_LOCATION);
+
+  animation.SetBlendPoint(0.5f);
+
+  DALI_TEST_EQUALS(animation.GetBlendPoint(), 0.5f, 0.01f, TEST_LOCATION);
+
+  animation.SetBlendPoint(-0.5f);
+
+  DALI_TEST_EQUALS(animation.GetBlendPoint(), 0.5f, 0.01f, TEST_LOCATION);
+
+  animation.SetBlendPoint(1.5f);
+
+  DALI_TEST_EQUALS(animation.GetBlendPoint(), 0.5f, 0.01f, TEST_LOCATION);
+
+  animation.SetBlendPoint(0.7f);
+
+  DALI_TEST_EQUALS(animation.GetBlendPoint(), 0.7f, 0.01f, TEST_LOCATION);
+
+  END_TEST;
+}
+
+int UtcDaliAnimationPlayBlendFloatCubic(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  application.GetScene().Add(actor);
+  Property::Index index = actor.RegisterProperty("property", 0.0f);
+
+  Animation animation = Animation::New(1.0f);
+  KeyFrames keyframes = KeyFrames::New();
+  keyframes.Add(0.0f, 3.0f);
+  keyframes.Add(0.4f, 1.0f);
+  keyframes.Add(0.6f, 1.0f);
+  keyframes.Add(1.0f, 3.0f);
+  animation.AnimateBetween(Property(actor, index), keyframes, AlphaFunction::LINEAR, Animation::Interpolation::CUBIC);
+
+  application.SendNotification();
+  application.Render(20);
+
+  animation.SetBlendPoint(0.5f);
+  animation.Play();
+
+  application.SendNotification();
+  application.Render(250);
+
+  float value = actor.GetCurrentProperty<float>(index);
+  DALI_TEST_EQUALS(value, 0.989258f, 0.05f, TEST_LOCATION); // original value : 1.603516 (Same value as when progress is 0.75.)
+                                                            // current value : 0.0f
+                                                            // value when progress is 0.5 : 0.75
+
+  application.SendNotification();
+  application.Render(250);
+
+  value = actor.GetCurrentProperty<float>(index);
+  DALI_TEST_EQUALS(value, 0.750000f, 0.05f, TEST_LOCATION); // value is less than 1.0f
+
+  application.SendNotification();
+  application.Render(250);
+
+  value = actor.GetCurrentProperty<float>(index);
+  DALI_TEST_EQUALS(value, 1.603516f, 0.05f, TEST_LOCATION);
+
+  application.SendNotification();
+  application.Render(250);
+
+  value = actor.GetCurrentProperty<float>(index);
+  DALI_TEST_EQUALS(value, 3.0f, 0.05f, TEST_LOCATION);
+
+  END_TEST;
+}
+
+int UtcDaliAnimationPlayBlendFloat1(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  application.GetScene().Add(actor);
+  Property::Index index = actor.RegisterProperty("property", 0.0f);
+
+  Animation animation = Animation::New(1.0f);
+  KeyFrames keyframes = KeyFrames::New();
+  keyframes.Add(0.0f, 1.0f);
+  keyframes.Add(0.2f, 2.0f);
+  keyframes.Add(0.4f, 3.0f);
+  keyframes.Add(0.6f, 4.0f);
+  keyframes.Add(0.8f, 5.0f);
+  keyframes.Add(1.0f, 6.0f);
+  animation.AnimateBetween(Property(actor, index), keyframes, AlphaFunction::LINEAR);
+
+  application.SendNotification();
+  application.Render(20);
+
+  animation.SetBlendPoint(0.9f);
+  animation.Play();
+
+  application.SendNotification();
+  application.Render(250);
+
+  float value = actor.GetCurrentProperty<float>(index);
+  DALI_TEST_EQUALS(value, 1.728395f, 0.05f, TEST_LOCATION);
+
+  application.SendNotification();
+  application.Render(250);
+
+  value = actor.GetCurrentProperty<float>(index);
+  DALI_TEST_EQUALS(value, 3.302469f, 0.05f, TEST_LOCATION);
+
+  application.SendNotification();
+  application.Render(250);
+
+  value = actor.GetCurrentProperty<float>(index);
+  DALI_TEST_EQUALS(value, 4.722222f, 0.05f, TEST_LOCATION);
+
+  application.SendNotification();
+  application.Render(250);
+
+  value = actor.GetCurrentProperty<float>(index);
+  DALI_TEST_EQUALS(value, 6.0f, 0.05f, TEST_LOCATION);
+
+  END_TEST;
+}
+
+int UtcDaliAnimationPlayBlendFloat2(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  application.GetScene().Add(actor);
+  Property::Index index = actor.RegisterProperty("property", 0.0f);
+
+  Animation animation = Animation::New(1.0f);
+  KeyFrames keyframes = KeyFrames::New();
+  keyframes.Add(0.0f, 0.0f);
+  keyframes.Add(1.0f, 1.0f);
+  animation.AnimateBetween(Property(actor, index), keyframes, AlphaFunction::LINEAR);
+
+  application.SendNotification();
+  application.Render(20);
+
+  animation.SetBlendPoint(0.5f);
+  animation.Play();
+
+  application.SendNotification();
+  application.Render(250);
+
+  float value = actor.GetCurrentProperty<float>(index);
+  DALI_TEST_EQUALS(value, 0.25f, 0.05f, TEST_LOCATION);
+
+  application.SendNotification();
+  application.Render(250);
+
+  value = actor.GetCurrentProperty<float>(index);
+  DALI_TEST_EQUALS(value, 0.5f, 0.05f, TEST_LOCATION);
+
+  END_TEST;
+}
+
+int UtcDaliAnimationPlayBlendFloat3(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  application.GetScene().Add(actor);
+  Property::Index index = actor.RegisterProperty("property", 0.0f);
+
+  Animation animation = Animation::New(1.0f);
+  KeyFrames keyframes = KeyFrames::New();
+  keyframes.Add(0.0f, 1.0f);
+  keyframes.Add(1.0f, 2.0f);
+  animation.AnimateBetween(Property(actor, index), keyframes, AlphaFunction::LINEAR);
+
+  application.SendNotification();
+  application.Render(20);
+
+  animation.SetBlendPoint(0.5f);
+  animation.Play();
+
+  application.SendNotification();
+  application.Render(250);
+
+  float value = actor.GetCurrentProperty<float>(index);
+  DALI_TEST_EQUALS(value, 1.0f, 0.05f, TEST_LOCATION);
+
+  application.SendNotification();
+  application.Render(250);
+
+  value = actor.GetCurrentProperty<float>(index);
+  DALI_TEST_EQUALS(value, 1.5f, 0.05f, TEST_LOCATION);
+
+  END_TEST;
+}
+
+int UtcDaliAnimationPlayBlendFloat4(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  application.GetScene().Add(actor);
+  Property::Index index = actor.RegisterProperty("property", 0.0f);
+
+  Animation animation = Animation::New(1.0f);
+  KeyFrames keyframes = KeyFrames::New();
+  keyframes.Add(0.0f, 1.0f);
+  keyframes.Add(1.0f, 2.0f);
+  animation.AnimateBetween(Property(actor, index), keyframes, AlphaFunction::LINEAR);
+
+  application.SendNotification();
+  application.Render(20);
+
+  animation.SetBlendPoint(0.5f);
+  animation.Play();
+
+  application.SendNotification();
+  application.Render(250);
+
+  float value = actor.GetCurrentProperty<float>(index);
+  DALI_TEST_EQUALS(value, 1.0f, 0.05f, TEST_LOCATION);
+
+  application.SendNotification();
+  application.Render(250);
+
+  value = actor.GetCurrentProperty<float>(index);
+  DALI_TEST_EQUALS(value, 1.5f, 0.05f, TEST_LOCATION);
+
+  application.SendNotification();
+  application.Render(550);
+
+  actor.SetProperty(index, 0.0f);
+  animation.Play();
+
+  application.SendNotification();
+  application.Render(250);
+
+  value = actor.GetCurrentProperty<float>(index);
+  DALI_TEST_EQUALS(value, 1.0f, 0.05f, TEST_LOCATION);
+
+  application.SendNotification();
+  application.Render(250);
+
+  value = actor.GetCurrentProperty<float>(index);
+  DALI_TEST_EQUALS(value, 1.5f, 0.05f, TEST_LOCATION);
+
+  END_TEST;
+}
+
+int UtcDaliAnimationPlayBlendInt(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  application.GetScene().Add(actor);
+  Property::Index index = actor.RegisterProperty("property", 0);
+
+  Animation animation = Animation::New(1.0f);
+  KeyFrames keyframes = KeyFrames::New();
+  keyframes.Add(0.0f, 100);
+  keyframes.Add(1.0f, 200);
+  animation.AnimateBetween(Property(actor, index), keyframes, AlphaFunction::LINEAR);
+
+  application.SendNotification();
+  application.Render(20);
+
+  animation.SetBlendPoint(0.5f);
+  animation.Play();
+
+  application.SendNotification();
+  application.Render(250);
+
+  int32_t value = actor.GetCurrentProperty<int32_t>(index);
+  DALI_TEST_EQUALS(value, 100, TEST_LOCATION);
+
+  application.SendNotification();
+  application.Render(250);
+
+  value = actor.GetCurrentProperty<int32_t>(index);
+  DALI_TEST_EQUALS(value, 150, TEST_LOCATION);
+
+  END_TEST;
+}
+
+int UtcDaliAnimationPlayBlendVector2(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  application.GetScene().Add(actor);
+  Property::Index index = actor.RegisterProperty("property", Vector2::ZERO);
+
+  Animation animation = Animation::New(1.0f);
+  KeyFrames keyframes = KeyFrames::New();
+  keyframes.Add(0.0f, Vector2::ONE);
+  keyframes.Add(1.0f, Vector2::ONE * 2.0f);
+  animation.AnimateBetween(Property(actor, index), keyframes, AlphaFunction::LINEAR);
+
+  application.SendNotification();
+  application.Render(20);
+
+  animation.SetBlendPoint(0.5f);
+  animation.Play();
+
+  application.SendNotification();
+  application.Render(250);
+
+  Vector2 value = actor.GetCurrentProperty<Vector2>(index);
+  DALI_TEST_EQUALS(value, Vector2::ONE, 0.05f, TEST_LOCATION);
+
+  application.SendNotification();
+  application.Render(250);
+
+  value = actor.GetCurrentProperty<Vector2>(index);
+  DALI_TEST_EQUALS(value, Vector2::ONE * 1.5f, 0.05f, TEST_LOCATION);
+
+  END_TEST;
+}
+
+int UtcDaliAnimationPlayBlendVector3(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  application.GetScene().Add(actor);
+  Property::Index index = actor.RegisterProperty("property", Vector3::ZERO);
+
+  Animation animation = Animation::New(1.0f);
+  KeyFrames keyframes = KeyFrames::New();
+  keyframes.Add(0.0f, Vector3::ONE);
+  keyframes.Add(1.0f, Vector3::ONE * 2.0f);
+  animation.AnimateBetween(Property(actor, index), keyframes, AlphaFunction::LINEAR);
+
+  application.SendNotification();
+  application.Render(20);
+
+  animation.SetBlendPoint(0.5f);
+  animation.Play();
+
+  application.SendNotification();
+  application.Render(250);
+
+  Vector3 value = actor.GetCurrentProperty<Vector3>(index);
+  DALI_TEST_EQUALS(value, Vector3::ONE, 0.05f, TEST_LOCATION);
+
+  application.SendNotification();
+  application.Render(250);
+
+  value = actor.GetCurrentProperty<Vector3>(index);
+  DALI_TEST_EQUALS(value, Vector3::ONE * 1.5f, 0.05f, TEST_LOCATION);
+
+  END_TEST;
+}
+
+int UtcDaliAnimationPlayBlendVector4(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  application.GetScene().Add(actor);
+  Property::Index index = actor.RegisterProperty("property", Vector4::ZERO);
+
+  Animation animation = Animation::New(1.0f);
+  KeyFrames keyframes = KeyFrames::New();
+  keyframes.Add(0.0f, Vector4::ONE);
+  keyframes.Add(1.0f, Vector4::ONE * 2.0f);
+  animation.AnimateBetween(Property(actor, index), keyframes, AlphaFunction::LINEAR);
+
+  application.SendNotification();
+  application.Render(20);
+
+  animation.SetBlendPoint(0.5f);
+  animation.Play();
+
+  application.SendNotification();
+  application.Render(250);
+
+  Vector4 value = actor.GetCurrentProperty<Vector4>(index);
+  DALI_TEST_EQUALS(value, Vector4::ONE, 0.05f, TEST_LOCATION);
+
+  application.SendNotification();
+  application.Render(250);
+
+  value = actor.GetCurrentProperty<Vector4>(index);
+  DALI_TEST_EQUALS(value, Vector4::ONE * 1.5f, 0.05f, TEST_LOCATION);
+
+  END_TEST;
+}
+
+int UtcDaliAnimationPlayBlendQuaternion(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  application.GetScene().Add(actor);
+  Property::Index index = actor.RegisterProperty("property", Quaternion(Dali::Radian(0.0f), Vector3::ZAXIS));
+
+  Animation animation = Animation::New(1.0f);
+  KeyFrames keyframes = KeyFrames::New();
+  keyframes.Add(0.0f, Quaternion(Dali::Radian(1.0f), Vector3::ZAXIS));
+  keyframes.Add(1.0f, Quaternion(Dali::Radian(2.0f), Vector3::ZAXIS));
+  animation.AnimateBetween(Property(actor, index), keyframes, AlphaFunction::LINEAR);
+
+  application.SendNotification();
+  application.Render(20);
+
+  animation.SetBlendPoint(0.5f);
+  animation.Play();
+
+  application.SendNotification();
+  application.Render(250);
+
+  Quaternion   value = actor.GetCurrentProperty<Quaternion>(index);
+  Vector3      axis;
+  Dali::Radian angle;
+  DALI_TEST_EQUALS(value.ToAxisAngle(axis, angle), true, TEST_LOCATION);
+  DALI_TEST_EQUALS(angle.radian, 1.0f, 0.05f, TEST_LOCATION);
+
+  application.SendNotification();
+  application.Render(250);
+
+  value = actor.GetCurrentProperty<Quaternion>(index);
+  DALI_TEST_EQUALS(value.ToAxisAngle(axis, angle), true, TEST_LOCATION);
+  DALI_TEST_EQUALS(angle.radian, 1.5f, 0.05f, TEST_LOCATION);
+
+  END_TEST;
+}