testDepthwiseConv2dGrad :: Test
testDepthwiseConv2dGrad = testCase "testDepthwiseConv2dGrad" $ do
    (dx, shapeDX, shapeX) <- TF.runSession $ do
        let conv_input_shape = TF.vector [1, 2, 2, 1 :: Int32]
        x <- TF.render $ TF.fill conv_input_shape (TF.scalar (2 :: Float))

        let filterShape = TF.vector [2, 2, 1, 1 :: Int32]
        filter' <- TF.render $ TF.fill filterShape (TF.scalar (1 :: Float))
        let y = TF.depthwiseConv2dNative'
                (TF.opAttr "strides" .~ [1 :: Int64, 1, 1, 1])
                TF.PaddingValid TF.ChannelLast x filter'

        [dx] <- TF.gradients y [x]
        TF.run (dx, TF.shape dx, TF.shape x)
    shapeX @=? (shapeDX :: V.Vector Int32)
    V.fromList [1, 1, 1, 1 :: Float] @=? (dx :: V.Vector Float)

-- TODO also test filter gradient
testDepthwiseConv2dGrad :: Test
testDepthwiseConv2dGrad = testCase "testDepthwiseConv2dGrad" $ do
    (dx, shapeDX, shapeX) <- TF.runSession $ do
        let conv_input_shape = TF.vector [1, 2, 2, 1 :: Int32]
        x <- TF.render $ TF.fill conv_input_shape (TF.scalar (2 :: Float))

        let filterShape = TF.vector [2, 2, 1, 1 :: Int32]
        filter' <- TF.render $ TF.fill filterShape (TF.scalar (1 :: Float))
        let y = TF.depthwiseConv2dNative'
                (TF.opAttr "strides" .~ [1 :: Int64, 1, 1, 1])
                TF.PaddingValid TF.ChannelLast x filter'

        [dx] <- TF.gradients y [x]
        TF.run (dx, TF.shape dx, TF.shape x)
    shapeX @=? (shapeDX :: V.Vector Int32)
    V.fromList [1, 1, 1, 1 :: Float] @=? (dx :: V.Vector Float)

-- TODO also test filter gradient
testDepthwiseConv2dGrad = testCase "testDepthwiseConv2dGrad" $ do
    (dx, shapeDX, shapeX) <- TF.runSession $ do
        let conv_input_shape = TF.vector [1, 2, 2, 1 :: Int32]
        x <- TF.render $ TF.fill conv_input_shape (TF.scalar (2 :: Float))

        let filterShape = TF.vector [2, 2, 1, 1 :: Int32]
        filter' <- TF.render $ TF.fill filterShape (TF.scalar (1 :: Float))
        let y = TF.depthwiseConv2dNative'
                (TF.opAttr "strides" .~ [1 :: Int64, 1, 1, 1])
                TF.PaddingValid TF.ChannelLast x filter'

        [dx] <- TF.gradients y [x]
        TF.run (dx, TF.shape dx, TF.shape x)
    shapeX @=? (shapeDX :: V.Vector Int32)
    V.fromList [1, 1, 1, 1 :: Float] @=? (dx :: V.Vector Float)

-- TODO also test filter gradient